2 * lock.c -- cross-platform concurrency locking for fetchmail
4 * For license terms, see the file COPYING in this directory.
10 #include <string.h> /* strcat() */
12 #if defined(STDC_HEADERS)
15 #if defined(HAVE_UNISTD_H)
22 #include "fetchmail.h"
26 static char *lockfile; /* name of lockfile */
27 static int lock_acquired; /* have we acquired a lock */
29 void fm_lock_setup(struct runctl *ctl)
30 /* set up the global lockfile name */
32 /* set up to do lock protocol */
33 const char *const FETCHMAIL_PIDFILE="fetchmail.pid";
35 /* command-line option override */
37 lockfile = xstrdup(ctl->pidfile);
42 if (getuid() == ROOT_UID) {
43 lockfile = (char *)xmalloc(strlen(PID_DIR)
44 + strlen(FETCHMAIL_PIDFILE) + 2); /* 2: "/" and NUL */
45 strcpy(lockfile, PID_DIR);
46 strcat(lockfile, "/");
47 strcat(lockfile, FETCHMAIL_PIDFILE);
49 lockfile = (char *)xmalloc(strlen(fmhome)
50 + strlen(FETCHMAIL_PIDFILE) + 3); /* 3: "/", "." and NUL */
51 strcpy(lockfile, fmhome);
52 strcat(lockfile, "/");
54 strcat(lockfile, ".");
55 strcat(lockfile, FETCHMAIL_PIDFILE);
59 static void unlockit(void)
60 /* must-do actions for exit (but we can't count on being able to do malloc) */
62 if (lockfile && lock_acquired)
66 void fm_lock_dispose(void)
67 /* arrange for a lock to be removed on process exit */
74 int fm_lock_state(void)
80 if ((lockfp = fopen(lockfile, "r")) != NULL)
82 int args = fscanf(lockfp, "%d %d", &pid, &st);
86 fprintf(stderr, GT_("fetchmail: error reading lockfile \"%s\": %s\n"),
87 lockfile, strerror(errno));
88 fclose(lockfp); /* not checking should be safe, file mode was "r" */
91 fclose(lockfp); /* not checking should be safe, file mode was "r" */
93 if (args == EOF || args == 0 || kill(pid, 0) == -1) {
96 fprintf(stderr,GT_("fetchmail: removing stale lockfile\n"));
97 if (unlink(lockfile)) {
98 if (errno != ENOENT) {
105 if (errno != ENOENT) {
106 fprintf(stderr, GT_("fetchmail: error opening lockfile \"%s\": %s\n"),
107 lockfile, strerror(errno));
112 return(bkgd ? -pid : pid);
115 void fm_lock_assert(void)
116 /* assert that we already posess a lock */
118 lock_acquired = TRUE;
121 void fm_lock_or_die(void)
122 /* get a lock on a given host or exit */
127 if (!lock_acquired) {
130 if ((fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL, 0666)) != -1) {
133 snprintf(tmpbuf, sizeof(tmpbuf), "%ld\n", (long)getpid());
134 wr = write(fd, tmpbuf, strlen(tmpbuf));
135 if (wr == -1 || (size_t)wr != strlen(tmpbuf))
137 if (run.poll_interval)
139 snprintf(tmpbuf, sizeof(tmpbuf), "%d\n", run.poll_interval);
140 wr = write(fd, tmpbuf, strlen(tmpbuf));
141 if (wr == -1 || (size_t)wr != strlen(tmpbuf))
144 if (fsync(fd)) e = 1;
145 if (close(fd)) e = 1;
150 lock_acquired = TRUE;
153 fprintf(stderr, GT_("fetchmail: lock creation failed.\n"));
159 void fm_lock_release(void)
160 /* release a lock on a given host */
164 /* lock.c ends here */