diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2001-03-10 18:40:12 +0000 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2001-03-10 18:40:12 +0000 |
commit | 5c4a6c30ef367a77db035cd44def733e4ae02563 (patch) | |
tree | 59f58b4e8c35c767debdd41e637c8738413bacdf | |
parent | 68bed872a590eeb81dc965596e5101c5adf35ac3 (diff) | |
download | fetchmail-5c4a6c30ef367a77db035cd44def733e4ae02563.tar.gz fetchmail-5c4a6c30ef367a77db035cd44def733e4ae02563.tar.bz2 fetchmail-5c4a6c30ef367a77db035cd44def733e4ae02563.zip |
After refactoring.
svn path=/trunk/; revision=3227
-rw-r--r-- | Makefile.in | 4 | ||||
-rw-r--r-- | fetchmail.c | 108 | ||||
-rw-r--r-- | fetchmail.h | 5 | ||||
-rw-r--r-- | lock.c | 130 |
4 files changed, 154 insertions, 93 deletions
diff --git a/Makefile.in b/Makefile.in index e6f1abe8..ec659905 100644 --- a/Makefile.in +++ b/Makefile.in @@ -96,7 +96,7 @@ protobjs = rcfile_y.o rcfile_l.o socket.o getpass.o pop2.o pop3.o imap.o \ sink.o rfc822.o smtp.o xmalloc.o uid.o mxget.o md5ify.o cram.o \ kerberos.o gssapi.o opie.o rpa.o interface.o netrc.o base64.o \ error.o unmime.o conf.o checkalias.o smbdes.o smbencrypt.o smbmd4.o \ - smbutil.o ipv6-connect.o + smbutil.o ipv6-connect.o lock.o objs = $(protobjs) $(extras) $(EXTRAOBJ) @@ -112,7 +112,7 @@ srcs = $(srcdir)/socket.c $(srcdir)/getpass.c $(srcdir)/pop2.c \ $(srcdir)/base64.c $(srcdir)/error.c $(srcdir)/unmime.c \ $(srcdir)/conf.c $(srcdir)/checkalias.c $(srcdir)/smbdes.c \ $(srcdir)/smbencrypt.c $(srcdir)/smbmd4.c $(srcdir)/smbutil.c \ - $(srcdir)/ipv6-connect.c + $(srcdir)/ipv6-connect.c $(srcdir)/lock.c .SUFFIXES: .SUFFIXES: .o .c .h .y .l .ps .dvi .info .texi diff --git a/fetchmail.c b/fetchmail.c index 48998a0d..cac7b413 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -80,8 +80,6 @@ void *request = NULL; int requestlen = 0; #endif /* NET_SECURITY */ -static char *lockfile; /* name of lockfile */ -static int lock_acquired; /* have we acquired a lock */ static int querystatus; /* status of query */ static int successes; /* count number of successful polls */ static int activecount; /* count number of active entries */ @@ -91,17 +89,6 @@ static time_t parsetime; /* time of last parse */ static void terminate_run(int); static void terminate_poll(int); -#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); -} - #if defined(__FreeBSD__) && defined(__FreeBSD_USE_KVM) /* drop SGID kmem privileage until we need it */ static void dropprivs(void) @@ -145,7 +132,6 @@ int main(int argc, char **argv) { int st, bkgd = FALSE; int parsestatus, implicitmode = FALSE; - FILE *lockfp; struct query *ctl; netrc_entry *netrc_list; char *netrc_file, *tmpbuf; @@ -187,19 +173,14 @@ int main(int argc, char **argv) outlevel = O_NORMAL; /* - * We used to arrange for the lockfile to be removed on exit close + * We used to arrange for the lock to be removed on exit close * to where the lock was asserted. Now we need to do it here, because - * we might have re-executed in background with an existing lockfile + * we might have re-executed in background with an existing lock * as the result of a changed rcfile (see the code near the execvp(3) * call near the beginning of the polling loop for details). We want - * to be sure the lockfile gets nuked on any error exit, basically. + * to be sure the lock gets nuked on any error exit, basically. */ -#ifdef HAVE_ATEXIT - atexit(unlockit); -#endif -#ifdef HAVE_ON_EXIT - on_exit(unlockit, (char *)NULL); -#endif + lock_dispose(); if ((parsestatus = parsecmdline(argc,argv, &cmd_run, &cmd_opts)) < 0) exit(PS_SYNTAX); @@ -279,21 +260,8 @@ int main(int argc, char **argv) #endif report_init((run.poll_interval == 0 || nodetach) && !run.logfile); - /* set up to do lock protocol */ -#define FETCHMAIL_PIDFILE "fetchmail.pid" - if (!getuid()) { - xalloca(tmpbuf, char *, - sizeof(PID_DIR) + sizeof(FETCHMAIL_PIDFILE)); - sprintf(tmpbuf, "%s/%s", PID_DIR, FETCHMAIL_PIDFILE); - } else { - xalloca(tmpbuf, char *, strlen(fmhome) + sizeof(FETCHMAIL_PIDFILE) + 2); - strcpy(tmpbuf, fmhome); - strcat(tmpbuf, "/"); - if (fmhome == home) - strcat(tmpbuf, "."); - strcat(tmpbuf, FETCHMAIL_PIDFILE); - } -#undef FETCHMAIL_PIDFILE + /* construct the lockfile */ + lock_setup(); #ifdef HAVE_SETRLIMIT /* @@ -360,9 +328,6 @@ int main(int argc, char **argv) havercfile ? "" : _(" and "), havercfile ? "" : rcfile); - if (outlevel >= O_VERBOSE) - printf(_("Lockfile at %s\n"), tmpbuf); - if (querylist == NULL) fprintf(stderr, _("No mailservers set up -- perhaps %s is missing?\n"), @@ -380,29 +345,12 @@ int main(int argc, char **argv) } /* check for another fetchmail running concurrently */ - pid = -1; - if ((lockfile = (char *) malloc(strlen(tmpbuf) + 1)) == NULL) - { - report(stderr,_("fetchmail: cannot allocate memory for lock name.\n")); - exit(PS_EXCLUDE); - } - else - (void) strcpy(lockfile, tmpbuf); - 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 = -1; - bkgd = FALSE; - unlink(lockfile); - } - fclose(lockfp); /* not checking should be safe, file mode was "r" */ - } + pid = lock_state(); + bkgd = (pid < 0); + pid = bkgd ? -pid : pid; /* if no mail servers listed and nothing in background, we're done */ - if (!(quitmode && argc == 2) && pid == -1 && querylist == NULL) { + if (!(quitmode && argc == 2) && pid == 0 && querylist == NULL) { (void)fputs(_("fetchmail: no mailservers have been specified.\n"),stderr); exit(PS_SYNTAX); } @@ -410,7 +358,7 @@ int main(int argc, char **argv) /* perhaps user asked us to kill the other fetchmail */ if (quitmode) { - if (pid == -1) + if (pid == 0) { fprintf(stderr,_("fetchmail: no other fetchmail is running\n")); if (argc == 2) @@ -426,16 +374,16 @@ int main(int argc, char **argv) { fprintf(stderr,_("fetchmail: %s fetchmail at %d killed.\n"), bkgd ? _("background") : _("foreground"), pid); - unlink(lockfile); + lock_release(); if (argc == 2) exit(0); else - pid = -1; + pid = 0; } } /* another fetchmail is running -- wake it up or die */ - if (pid != -1) + if (pid != 0) { if (check_only) { @@ -461,7 +409,7 @@ int main(int argc, char **argv) { /* this test enables re-execing on a changed rcfile */ if (getpid() == pid) - lock_acquired = TRUE; + lock_assert(); else { fprintf(stderr, @@ -566,29 +514,7 @@ int main(int argc, char **argv) signal(SIGQUIT, terminate_run); /* here's the exclusion lock */ -#ifndef O_SYNC -#define O_SYNC 0 /* use it if we have it */ -#endif - if (!lock_acquired) - { - if ((st = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_SYNC, 0666)) != -1) - { - sprintf(tmpbuf,"%d", getpid()); - write(st, tmpbuf, strlen(tmpbuf)); - if (run.poll_interval) - { - sprintf(tmpbuf," %d", run.poll_interval); - write(st, tmpbuf, strlen(tmpbuf)); - } - close(st); /* should be safe, fd was opened with O_SYNC */ - lock_acquired = TRUE; - } - else - { - fprintf(stderr, _("fetchmail: lock creation failed.\n")); - return(PS_EXCLUDE); - } - } + lock_or_die(); /* * Query all hosts. If there's only one, the error return will @@ -1409,7 +1335,7 @@ static void terminate_run(int sig) memset(ctl->password, '\0', strlen(ctl->password)); #if !defined(HAVE_ATEXIT) && !defined(HAVE_ON_EXIT) - unlockit(); + lock_release(); #endif if (activecount == 0) diff --git a/fetchmail.h b/fetchmail.h index 6c9a4919..e5d576a0 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -414,6 +414,11 @@ int gen_recv(); int gen_transact (); #endif +/* lock.c: concurrency locking */ +void lock_setup(void), lock_assert(void); +void lock_or_die(void), lock_release(void); +int lock_state(void); + /* use these to track what was happening when the nonresponse timer fired */ #define GENERAL_WAIT 0 /* unknown wait type */ #define OPEN_WAIT 1 /* waiting from mailserver open */ @@ -0,0 +1,130 @@ +/* + * lock.c -- cross-platform concurrency locking for fetchmail + * + * For license terms, see the file COPYING in this directory. + */ +#include "config.h" + +#include <stdio.h> +#if defined(STDC_HEADERS) +#include <stdlib.h> +#endif +#if defined(HAVE_UNISTD_H) +#include <unistd.h> +#endif +#include <fcntl.h> + +#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()) { + xalloca(lockfile, char *, + sizeof(PID_DIR) + sizeof(FETCHMAIL_PIDFILE)); + sprintf(lockfile, "%s/%s", PID_DIR, FETCHMAIL_PIDFILE); + } else { + xalloca(lockfile, char *, 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 */ |