/* * lock.c -- cross-platform concurrency locking for fetchmail * * For license terms, see the file COPYING in this directory. */ #include "config.h" #include #ifdef HAVE_STRING_H #include /* strcat() */ #endif #if defined(STDC_HEADERS) #include #endif #if defined(HAVE_UNISTD_H) #include #endif #include #include #include "fetchmail.h" #include "i18n.h" static char *lockfile; /* name of lockfile */ static int lock_acquired; /* have we acquired a lock */ void lock_setup(void) /* set up the global lockfile name */ { /* set up to do lock protocol */ #define FETCHMAIL_PIDFILE "fetchmail.pid" if (!getuid()) { lockfile = (char *)xmalloc( sizeof(PID_DIR) + sizeof(FETCHMAIL_PIDFILE)); sprintf(lockfile, "%s/%s", PID_DIR, FETCHMAIL_PIDFILE); } else { lockfile = (char *)xmalloc(strlen(fmhome)+sizeof(FETCHMAIL_PIDFILE)+2); strcpy(lockfile, fmhome); strcat(lockfile, "/"); if (fmhome == home) strcat(lockfile, "."); strcat(lockfile, FETCHMAIL_PIDFILE); } #undef FETCHMAIL_PIDFILE } #ifdef HAVE_ON_EXIT static void unlockit(int n, void *p) #else static void unlockit(void) #endif /* must-do actions for exit (but we can't count on being able to do malloc) */ { if (lockfile && lock_acquired) unlink(lockfile); } void lock_dispose(void) /* arrange for a lock to be removed on process exit */ { #ifdef HAVE_ATEXIT atexit(unlockit); #endif #ifdef HAVE_ON_EXIT on_exit(unlockit, (char *)NULL); #endif } int lock_state(void) { int pid, st; FILE *lockfp; int bkgd = FALSE; pid = 0; if ((lockfp = fopen(lockfile, "r")) != NULL ) { bkgd = (fscanf(lockfp, "%d %d", &pid, &st) == 2); if (kill(pid, 0) == -1) { fprintf(stderr,_("fetchmail: removing stale lockfile\n")); pid = 0; unlink(lockfile); } fclose(lockfp); /* not checking should be safe, file mode was "r" */ } return(bkgd ? -pid : pid); } void lock_assert(void) /* assert that we already posess a lock */ { lock_acquired = TRUE; } void lock_or_die(void) /* get a lock on a given host or exit */ { int fd; char tmpbuf[20]; #ifndef O_SYNC #define O_SYNC 0 /* use it if we have it */ #endif if (!lock_acquired) { if ((fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_SYNC, 0666)) != -1) { sprintf(tmpbuf,"%d", getpid()); write(fd, tmpbuf, strlen(tmpbuf)); if (run.poll_interval) { sprintf(tmpbuf," %d", run.poll_interval); write(fd, tmpbuf, strlen(tmpbuf)); } close(fd); /* should be safe, fd was opened with O_SYNC */ lock_acquired = TRUE; } else { fprintf(stderr, _("fetchmail: lock creation failed.\n")); exit(PS_EXCLUDE); } } } void lock_release(void) /* release a lock on a given host */ { unlink(lockfile); } /* lock.c ends here */