diff options
-rw-r--r-- | README | 7 | ||||
-rw-r--r-- | daemon.c | 12 | ||||
-rw-r--r-- | fetchmail.c | 72 | ||||
-rw-r--r-- | fetchmail.h | 7 | ||||
-rw-r--r-- | fetchmail.man | 14 | ||||
-rw-r--r-- | options.c | 12 |
6 files changed, 120 insertions, 4 deletions
@@ -1,6 +1,9 @@ Popclient README $Log: README,v $ + Revision 1.3 1996/06/27 19:22:31 esr + Sent to ceharris. + Revision 1.2 1996/06/26 19:08:55 esr This is what I sent Harris. @@ -89,6 +92,10 @@ FUNCTIONAL ENHANCEMENTS * I have implemented daemon mode. +* I have added a lock check to ensure that there is only one popclient + running per user, and a --quit option to kill the currently running + one. + DOCUMENTATION * All changes and feature additions have been tested in actual use and are @@ -25,6 +25,9 @@ BSD systems. $Log: daemon.c,v $ + Revision 1.3 1996/06/27 19:22:31 esr + Sent to ceharris. + Revision 1.2 1996/06/26 19:08:57 esr This is what I sent Harris. @@ -57,6 +60,7 @@ #include "popclient.h" +static void (*my_termhook)(void); /****************************************************************** function: sigchld_handler @@ -80,6 +84,9 @@ sigchld_handler () int status; #endif + if (my_termhook) + (*my_termhook)(); + #if defined(HAVE_WAIT3) while ((pid = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0) ; /* swallow 'em up. */ @@ -109,8 +116,9 @@ sigchld_handler () *****************************************************************/ int -daemonize (logfile) +daemonize (logfile, termhook) const char *logfile; +void (*termhook)(void); { int fd; pid_t childpid; @@ -119,6 +127,8 @@ const char *logfile; /* if we are started by init (process 1) via /etc/inittab we needn't bother to detach from our process group context */ + my_termhook = termhook; + if (getppid() == 1) goto nottyDetach; diff --git a/fetchmail.c b/fetchmail.c index 10bff927..c85aec3a 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -22,6 +22,9 @@ description: main driver module for popclient $Log: fetchmail.c,v $ + Revision 1.3 1996/06/27 19:22:32 esr + Sent to ceharris. + Revision 1.2 1996/06/26 19:08:59 esr This is what I sent Harris. @@ -113,6 +116,7 @@ int outlevel; /* see the O_.* constants in popclient.h */ /* Daemon-mode control */ int poll_interval; /* polling interval for daemon mode */ char *logfile; /* logfile to ship progress reports to */ +int quitmode; /* if -quit was set */ /* args for the MDA, parsed out in the usual fashion by parseMDAargs() */ char *mda_argv [32]; @@ -130,6 +134,9 @@ char *mda_argv [32]; globals: none. *********************************************************************/ +static void termhook(); +static char *lockfile; + main (argc,argv) int argc; char **argv; @@ -140,6 +147,8 @@ char **argv; int parsestatus; char *servername; struct hostrec *hostp, *hostlist = (struct hostrec *)NULL; + FILE *tmpfp; + pid_t pid; if ((parsestatus = parsecmdline(argc,argv,&cmd_opts)) < 0) exit(PS_SYNTAX); @@ -190,11 +199,66 @@ char **argv; exit(PS_SYNTAX); } + /* beyond here we don't want more than one popclient running per user */ + umask(0077); + if ((lockfile = (char *) malloc( strlen(getenv("HOME")) + strlen("/.lockfetch-") + HOSTLEN)) == NULL) { + fprintf(stderr,"popclient: cannot allocate memory for .lockfetch, exiting.\n"); + exit(PS_EXCLUDE); + } + strcpy(lockfile, getenv("HOME")); + strcat(lockfile,"/.lockfetch-"); + gethostname(lockfile+strlen(lockfile),HOSTLEN); + + /* check the lock, maybe remove it */ + if (!quitmode) + { + /* check the lock */ + if ( (tmpfp = fopen(lockfile, "r")) != NULL ) { + fscanf(tmpfp,"%d",&pid); + fprintf(stderr,"Another session appears to be running at pid %d.\nIf you are sure that this is incorrect, remove %s file.\n",pid,lockfile); + fclose(tmpfp); + return(PS_EXCLUDE); + } + + /* if not locked, assert a lock */ + else if ( (tmpfp = fopen(lockfile,"w")) != NULL ) { + signal(SIGABRT, termhook); + signal(SIGINT, termhook); + signal(SIGTERM, termhook); + signal(SIGALRM, termhook); + signal(SIGHUP, termhook); + signal(SIGPIPE, termhook); + signal(SIGQUIT, termhook); + fprintf(tmpfp,"%d",getpid()); + fclose(tmpfp); + } + } + else + { + FILE* fp; + + if ( (fp = fopen(lockfile, "r")) == NULL ) { + fprintf(stderr,"popclient: no other popclient is running\n"); + return(PS_EXCLUDE); + } + + fscanf(fp,"%d",&pid); + fprintf(stderr,"popclient: killing popclient at PID %d\n",pid); + if ( kill(pid,SIGKILL) < 0 ) + fprintf(stderr,"popclient: error killing the process %d\n.",pid); + else + fprintf(stderr,"popclient: popclient at %d is dead.\n", pid); + + fclose(fp); + remove(lockfile); + exit(0); + } + /* * Maybe time to go to demon mode... */ if (poll_interval) - daemonize(logfile); + daemonize(logfile, termhook); /* * Query all hosts. If there's only one, the error return will @@ -209,9 +273,15 @@ char **argv; } while (poll_interval); + termhook(); exit(popstatus); } +void termhook() +{ + unlink(lockfile); +} + int query_host(servername, options) /* perform fetch transaction with single host */ char *servername; diff --git a/fetchmail.h b/fetchmail.h index 814605ad..0e85fc8e 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -23,6 +23,9 @@ description: global constant, type, and variable definitions. $Log: fetchmail.h,v $ + Revision 1.3 1996/06/27 19:22:33 esr + Sent to ceharris. + Revision 1.2 1996/06/26 19:08:59 esr This is what I sent Harris. @@ -85,6 +88,7 @@ #define PS_SYNTAX 5 /* command-line syntax error */ #define PS_IOERR 6 /* local folder I/O woes */ #define PS_ERROR 7 /* some kind of POP3 error condition */ +#define PS_EXCLUDE 8 /* exclusion error */ #define PS_UNDEFINED 9 /* something I hadn't thought of */ /* output noise level */ @@ -143,6 +147,7 @@ extern int yydebug; /* enable parse debugging */ /* daemon mode control */ extern int poll_interval; /* poll interval in seconds */ extern char *logfile; /* log file for daemon mode */ +extern int quitmode; /* if --quit was set */ extern char *prc_pathname; /* path name of rc file */ @@ -163,7 +168,7 @@ char *MD5Digest (char *); char *prc_getpathname (struct optrec *cmd_opts, struct optrec *def_opts); void reply_hack(char *buf, const char *host); void append_server_names(int *pargc, char **argv); -int daemonize(const char *logfile); +int daemonize(const char *logfile, void (*)(void)); #else diff --git a/fetchmail.man b/fetchmail.man index 46ee9f94..8eca7854 100644 --- a/fetchmail.man +++ b/fetchmail.man @@ -16,6 +16,9 @@ \. */ \. \. $Log: fetchmail.man,v $ +\. Revision 1.3 1996/06/27 19:22:33 esr +\. Sent to ceharris. +\. \. Revision 1.2 1996/06/26 19:09:00 esr \. This is what I sent Harris. \. @@ -371,6 +374,12 @@ popmail -d 900 will, therefore, poll the hosts described in your .I ~/.poprc file once every fifteen minutes. +.PP +Only one daemon process is permitted per user; in daemon mode, +.I popclient +makes a per-user lockfile to guarantee this. The option +.B --quit +will kill a running daemon process. .SH THE POPRC FILE The preferred way to set up popclient (and the only way if you want to specify a password) is to write a .poprc file in your home directory. @@ -520,6 +529,11 @@ There was a syntax error in the arguments to Some kind of I/O woes occurred when writing to the local folder. .IP 7 There was an error condition reported by the server (POP3 only). +.IP 8 +Exclusion error. This means +.I popclient +either found another copy of itself already running, or failed in such +a way that it isn't sure whether another copy is running. .IP 9 Something totally undefined occured. This is usually caused by a bug within .I popclient. @@ -22,6 +22,9 @@ description: command-line option processing $Log: options.c,v $ + Revision 1.3 1996/06/27 19:22:32 esr + Sent to ceharris. + Revision 1.2 1996/06/26 19:08:57 esr This is what I sent Harris. @@ -87,7 +90,8 @@ #define LA_LOCALFILE 15 #define LA_MDA 16 #define LA_LOGFILE 17 -#define LA_YYDEBUG 18 +#define LA_QUIT 18 +#define LA_YYDEBUG 19 static char *shortoptions = "23VaKkvscl:Fd:f:u:r:o:m:"; static struct option longoptions[] = { @@ -110,6 +114,7 @@ static struct option longoptions[] = { {"local", required_argument, (int *) 0, LA_LOCALFILE }, {"mda", required_argument, (int *) 0, LA_MDA }, {"logfile", required_argument, (int *) 0, LA_LOGFILE }, + {"quit", no_argument, (int *) 0, LA_QUIT }, {"yydebug", no_argument, (int *) 0, LA_YYDEBUG }, {(char *) 0, no_argument, (int *) 0, 0 } }; @@ -260,6 +265,10 @@ struct optrec *options; case LA_LOGFILE: logfile = optarg; break; + case 'q': + case LA_QUIT: + quitmode = 1; + break; case LA_YYDEBUG: yydebug = 1; break; @@ -283,6 +292,7 @@ struct optrec *options; fputs(" -k, --keep save new messages after retrieval\n", stderr); fputs(" -l, --limit retrieve at most n message lines\n", stderr); fputs(" -m, --mda set mail user agent to pass to\n", stderr); + fputs(" -q, --quit kill daemon process\n", stderr); fputs(" -s, --silent work silently\n", stderr); fputs(" -v, --verbose work noisily (diagnostic output)\n", stderr); fputs(" -d, --daemon run as a daemon once per n seconds\n", stderr); |