2 * This is a hack, but until libc and glibc both include this function
3 * by default (libc only includes it if nys is not being used, at the
4 * moment, and glibc doesn't appear to have it at all) we need to have
7 * This should not become an official part of PAM.
13 * lckpwdf.c -- prevent simultaneous updates of password files
15 * Before modifying any of the password files, call lckpwdf(). It may block
16 * for up to 15 seconds trying to get the lock. Return value is 0 on success
17 * or -1 on failure. When you are done, call ulckpwdf() to release the lock.
18 * The lock is also released automatically when the process exits. Only one
19 * process at a time may hold the lock.
21 * These functions are supposed to be conformant with AT&T SVID Issue 3.
23 * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
25 * $FreeBSD: src/contrib/libpam/modules/pam_unix/lckpwdf.-c,v 1.1.1.1.2.2 2001/06/11 15:28:30 markm Exp $
26 * $DragonFly: src/contrib/libpam/modules/pam_unix/Attic/lckpwdf.-c,v 1.2 2003/06/17 04:24:03 dillon Exp $
32 #define LOCKFILE "/etc/.pwd.lock"
35 static int lockfd = -1;
37 static int set_close_on_exec(int fd)
39 int flags = fcntl(fd, F_GETFD, 0);
43 return fcntl(fd, F_SETFD, flags);
46 static int do_lock(int fd)
50 memset(&fl, 0, sizeof fl);
52 fl.l_whence = SEEK_SET;
53 return fcntl(fd, F_SETLKW, &fl);
56 static void alarm_catch(int sig)
58 /* does nothing, but fcntl F_SETLKW will fail with EINTR */
61 static int lckpwdf(void)
63 struct sigaction act, oldact;
69 lockfd = open(LOCKFILE, O_CREAT | O_WRONLY, 0600);
72 if (set_close_on_exec(lockfd) == -1)
75 memset(&act, 0, sizeof act);
76 act.sa_handler = alarm_catch;
78 sigfillset(&act.sa_mask);
79 if (sigaction(SIGALRM, &act, &oldact) == -1)
83 sigaddset(&set, SIGALRM);
84 if (sigprocmask(SIG_UNBLOCK, &set, &oldset) == -1)
88 if (do_lock(lockfd) == -1)
91 sigprocmask(SIG_SETMASK, &oldset, NULL);
92 sigaction(SIGALRM, &oldact, NULL);
97 sigprocmask(SIG_SETMASK, &oldset, NULL);
99 sigaction(SIGALRM, &oldact, NULL);
106 static int ulckpwdf(void)
112 if (close(lockfd) == -1) {