aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README7
-rw-r--r--daemon.c12
-rw-r--r--fetchmail.c72
-rw-r--r--fetchmail.h7
-rw-r--r--fetchmail.man14
-rw-r--r--options.c12
6 files changed, 120 insertions, 4 deletions
diff --git a/README b/README
index c2894ba9..2445e7c2 100644
--- a/README
+++ b/README
@@ -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
diff --git a/daemon.c b/daemon.c
index cdfb35f9..0776d062 100644
--- a/daemon.c
+++ b/daemon.c
@@ -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.
diff --git a/options.c b/options.c
index 47c92094..199a182f 100644
--- a/options.c
+++ b/options.c
@@ -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);