home *** CD-ROM | disk | FTP | other *** search
- /* $Header: cleanque.c,v 1.6 85/04/05 13:42:13 long Exp $ */
- /*
- * MULTI-CHANNEL MEMO DISTRIBUTION FACILITY (MMDF)
- *
- *
- * Copyright (C) 1979,1980,1981 University of Delaware
- *
- * Department of Electrical Engineering
- * University of Delaware
- * Newark, Delaware 19711
- *
- * Phone: (302) 738-1163
- *
- *
- * This program module was developed as part of the University
- * of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
- *
- * Acquisition, use, and distribution of this module and its listings
- * are subject restricted to the terms of a license agreement.
- * Documents describing systems using this module must cite its source.
- *
- * The above statements must be retained with all copies of this
- * program and may not be removed without the consent of the
- * University of Delaware.
- *
- *
- * version -1 David H. Crocker March 1979
- * version 0 David H. Crocker April 1980
- * version v7 David H. Crocker May 1981
- * version 1 David H. Crocker October 1981
- *
- */
- #include "util.h"
- #include "mmdf.h"
- #include "msg.h"
- #include "adr_queue.h"
- #include "ch.h"
- #include <sys/stat.h>
-
- /* QUECLEAN: Clean up the mail queue directories */
-
- /* Jul 80 Dave Crocker noaddr, correct the 2d multcpy
- * Aug 80 Dave Crocker fix orphaned
- * Aug 80 Dave Crocker fix name-handling for mclean
- * Aug 81 Dave Crocker test for chdir failures
- * Mar 83 Doug Kingston modified to use format independent directory
- * access routines a la 4.2BSD. (libndir.a)
- */
-
- /*#define RUNALON */
-
- #define MINAGE (long) (60 * 60 * 4)
- /* at least four hours old */
-
- extern int warntime; /* hours to wait before notification */
- extern int failtime; /* hours to wait before returning msg */
- extern int errno;
- extern LLog msglog;
- LLog *logptr = &msglog;
-
- extern char *quedfldir,
- *aquedir,
- *squepref,
- *tquedir,
- *mquedir,
- *supportaddr;
-
- DIR *quep; /* for reading directory entries */
-
- struct stat testnode;
-
- time_t curtime; /* Current time in hours */
- int elaphour; /* Message waiting time in hours */
-
- char aname[LINESIZE],
- mname[LINESIZE];
-
- int effecid, /* system number of pgm/file's owner */
- callerid; /* who invoked me? */
-
- LOCFUN ismsg(), msg_dequeue(), mn_mmdf();
-
- /**/
-
- main (argc, argv) /* remove old queue files */
- int argc;
- char *argv[];
- {
- extern char *dupfpath ();
- extern time_t time ();
-
- mmdf_init (argv[0]);
- nice (-5); /* try to run faster, if root */
-
- getwho (&callerid, &effecid); /* who am I and who is running me? */
- mn_mmdf(); /* set up effective and group id's properly */
-
- if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'w')
- domsg = TRUE;
-
- time (&curtime);
-
- if (chdir (quedfldir) < OK || chdir (tquedir) < OK)
- {
- printx ("couldn't chdir to tquedir\n");
- ll_err (logptr, LLOGFAT, "couldn't chdir tquedir");
- exit (-1);
- }
-
- tclean (); /* clean out temporary files */
-
- if (chdir (quedfldir) < OK)
- {
- printx ("couldn't chdir to quedfldir\n");
- ll_log (logptr, LLOGFAT, "couldn't chdir to quedfldir");
- exit (-1);
- }
-
- mclean (); /* get rid of orphaned text files */
-
- if (chdir (quedfldir) < OK)
- {
- printx ("couldn't chdir to quedfldir\n");
- ll_log (logptr, LLOGFAT, "couldn't chdir to quedfldir");
- exit (-1);
- }
-
- aclean (); /* get rid of old queued messages */
- }
- /* *************** GET RID OF OLD TEMPORARY FILES **************** */
-
- tclean () /* clean out temporary files */
- {
- register struct dirtype *dp;
-
- if ((quep = opendir (".")) == NULL)
- {
- printx ("couldn't open tquedir\n");
- ll_log (logptr, LLOGFAT, "couldn't open tquedir");
- exit (-1);
- }
-
- while ((dp = readdir (quep)) != NULL)
- if (ismsg (dp) && minage (dp->d_name))
- {
- printx ("removing temp file: %s\n", dp->d_name);
- ll_log (logptr, LLOGGEN, "removing temp file: %s", dp->d_name);
-
- #ifndef RUNALON
- (void) unlink (dp->d_name);
- #endif
- }
-
- closedir (quep);
- }
- /* *************** GET RID OF ORPHANED TEXT FILES **************** */
-
- mclean () /* get rid of orphaned text files */
- {
- register struct dirtype *dp;
-
- if ((quep = opendir (mquedir)) == NULL)
- {
- printx ("couldn't open quedfldir\n");
- ll_log (logptr, LLOGFAT, "couldn't open quedfldir");
- exit (-1);
- }
-
- while ((dp = readdir (quep)) != NULL)
- if (ismsg (dp))
- mproc (dp->d_name);
-
- closedir (quep);
- quep = (DIR *) EOF;
- }
-
- mproc (filename) /* check for & remove orphaned msgs */
- char filename[];
- {
- (void) sprintf (mname, "%s%s", mquedir, filename);
- (void) sprintf (aname, "%s%s", aquedir, filename);
-
- if (minage (mname) && stat (aname, &testnode) == -1)
- { /* old & no aquedir association */
- printx ("removing old orphaned text file: %s\n", filename);
- ll_log (logptr, LLOGGEN, "removing text file: %s", filename);
-
- #ifndef RUNALON
- (void) unlink (mname);
- #endif
- }
- }
-
- /**/
-
- minage (filename) /* is file more than x hours old? */
- char filename[];
- {
- if (stat (filename, &testnode) == -1)
- return (FALSE); /* doesn't really exist */
-
- #ifdef RUNALON
- printx ("O? %s\n", filename);
- #endif
-
- return (((curtime - testnode.st_mtime) > MINAGE) ? TRUE : FALSE);
- /* two hours since modified? */
- }
- /* ************** GET RID OF MESSAGES IN QUEUE TOO LONG ********** */
-
- aclean ()
- {
- Msg themsg;
- char retadr[LINESIZE];
- register struct dirtype *dp;
-
- if ((quep = opendir (aquedir)) == NULL)
- err_abrt (RP_FOPN, "can't open address queue");
-
- themsg.mg_null = '\0';
- while ((dp = readdir (quep)) != NULL)
- if (ismsg (dp))
- {
- /* get queue entry name (msg name) */
- (void) strcpy (themsg.mg_mname, dp->d_name);
- if (mq_rinit ((Chan *) 0, &themsg, retadr) != OK)
- continue;
- elaphour = (int) ((curtime - themsg.mg_time) / (time_t) 3600);
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR,
- "%s (%d hrs)", themsg.mg_mname, elaphour);
- #endif
- if (elaphour > warntime) /* message is old */
- {
- if (elaphour > failtime)
- {
- /* old enough to return? */
- doreturn (&themsg, retadr);
- deque (&themsg);
- }
- else if (!msg_warned(themsg.mg_stat))
- dowarn (&themsg, retadr);
- }
- mq_rkill (OK);
- }
-
- closedir (quep);
- quep = (DIR *) EOF;
- }
-
- /**/
-
- LOCFUN
- ismsg (theentry) /* a processable message? */
- register struct dirtype *theentry;
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "ovr_ismsg (name='%s')",
- theentry -> d_name);
- #endif
-
- /* valid message: entry allocated & name begins with "msg." */
-
- return ((
- #ifdef BSDDIRECT
- theentry -> d_namlen < MSGNSIZE
- #else
- (strlen(theentry->d_name) < MSGNSIZE)
- #endif
- && equal (theentry -> d_name, "msg.", 4)) ? TRUE : FALSE);
- }
-
- deque (themsg)
- Msg *themsg;
- {
- struct adr_struct theadr;
- char curque[ADDRSIZE];
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "deque");
- #endif
-
- curque[0] = '\0'; /* no queue in effect */
-
- mq_setpos (0L); /* start at the beginning of the queue */
- while (mq_radr (&theadr) == OK)
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR,
- "(%c)%s:%s", theadr.adr_delv, theadr.adr_que, curque);
- #endif
- /*
- * We have to dequeue from every queue since the return
- * function already has marked all the addresses as "DONE".
- * The msg_dequeue function was modified to ignore ENOENT
- * so if the file is already gone, it is not an error.
- */
- if (!lexequ (curque, theadr.adr_que))
- {
- (void) strcpy (curque, theadr.adr_que);
- msg_dequeue (theadr.adr_que, themsg);
- }
- }
- msg_dequeue ((char *) 0, themsg);
- }
- /**/
-
- LOCFUN
- msg_dequeue (theque, themsg) /* remove message from queue */
- char *theque;
- Msg *themsg;
- {
- char thename[LINESIZE];
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "msg_deque (%s,%s)",
- (theque == (char *) 0) ? "(Base entry)" : theque,
- themsg -> mg_mname);
- #endif
- #ifdef RUNALON
- return;
- #endif
-
- if (theque == (char *) 0)
- (void) sprintf (thename, "%s%s", aquedir, themsg -> mg_mname);
- else
- (void) sprintf (thename, "%s%s/%s",
- squepref, theque, themsg -> mg_mname);
-
- if (unlink (thename) < OK && errno != ENOENT) {
- /* this is real queue handle */
- ll_err (logptr, LLOGTMP, "Problem unlinking '%s' address: %s",
- themsg -> mg_mname, thename);
- }
-
- if (theque == (char *) 0)
- { /* get rid of ALL the message */
- (void) sprintf (thename, "%s%s", mquedir, themsg -> mg_mname);
- if (unlink (thename) < OK) /* the text is just "baggage" */
- ll_err (logptr, LLOGTMP, "Problem unlinking %s text: '%s'",
- themsg -> mg_mname, thename);
- }
- }
- /**/
-
- dowarn (themsg, retadr)
- Msg *themsg;
- char retadr[];
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "dowarn (%s, %s)", themsg -> mg_mname, retadr);
- #endif
-
- printx ("%s: delivery overdue; ", themsg -> mg_mname);
- (void) fflush (stdout);
-
- if (msg_nowarn (themsg -> mg_stat)) {
- printx ("warning not wanted\n");
- }
- else if (rtn_warn (themsg, retadr) == OK)
- { /* flag as already warned */
- printx ("warning sent\n");
- ll_log (logptr, LLOGGEN, "warn *** Time warning (%s, %s)",
- themsg -> mg_mname, retadr);
- }
- else
- {
- printx ("couldn't send warning\n");
- ll_err (logptr, LLOGTMP, "warn *** Couldn't time warn (%s, %s)",
- themsg -> mg_mname, retadr);
- }
- (void) fflush (stdout);
-
- mq_rwarn ();
- }
-
- doreturn (themsg, retadr)
- Msg *themsg;
- char retadr[];
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "doreturn (%s, %s)", themsg -> mg_mname, retadr);
- #endif
-
- printx ("%s: not delivered in time; waiting %d hrs;", themsg -> mg_mname, elaphour);
- (void) fflush (stdout);
- if (msg_noret (themsg -> mg_stat)) {
- printx (" error return not wanted\n");
- }
- else if (rtn_time (themsg, retadr) == OK)
- { /* dequeue if couldn't notify */
- printx (" returned\n");
- (void) fflush (stdout);
- ll_log (logptr, LLOGTMP, "ret *** Timeout return (%s, %s)",
- themsg -> mg_mname, retadr);
- }
- else
- { /* dequeue if couldn't notify */
- char orphanage[ADDRSIZE];
-
- (void) sprintf (orphanage, "Orphanage <%s>", supportaddr);
- printx (" couldn't return,\ntrying orphanage...");
- (void) fflush (stdout);
- if (rtn_time (themsg, orphanage) == OK)
- {
- printx (" returned to orphanage.\n");
- (void) fflush (stdout);
- }
- else
- {
- ll_err (logptr, LLOGTMP, "ret *** Timeout couldn't return (%s,%s)",
- themsg -> mg_mname, retadr);
- dead_letter (themsg->mg_mname, "Timeout on delivery");
- }
- }
- }
-
-
- /**/
-
- LOCFUN
- mn_mmdf () /* setuid to mmdf: bypass being root */
- { /* get sys id for mmdf; setuid to it */
- extern char *pathsubmit; /* submit command file name */
- extern char *cmddfldir; /* directory w/mmdf commands */
- char temppath[LINESIZE];
- struct stat statbuf;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGPTR, "mn_mmdf(); effec==%d",
- effecid );
- #endif
-
- /* the following is a little strange, doing a stat on the object
- * file, because setuid-on-execute does not work when the caller
- * is root, as will happen when this is started by the rc file.
- * hence, the effective id, from a getuid, will show root & not mmdf.
- *
- * the goal is to have this process be name-independent of the caller,
- * so that returned mail comes from mmdf and not the invoker.
- *
- * in pickup mode, the id of the caller has to be retained, since
- * pobox channels use that to determine access rights to mail.
- *
- * All sets gid to mmdf's gid -- <DPK@BRL>
- */
-
- if (effecid == 0)
- {
- getfpath (pathsubmit, cmddfldir, temppath);
-
- if (stat (temppath, &statbuf) < OK)
- err_abrt (RP_LIO, "Unable to stat %s", temppath);
- /* use "submit" to get mmdf id */
-
- if (setgid (statbuf.st_gid) == NOTOK)
- err_abrt (RP_LIO, "Can't setgid to mmdf (%d)", statbuf.st_gid);
- if (setuid (statbuf.st_uid) == NOTOK)
- err_abrt (RP_LIO, "Can't setuid to mmdf (%d)", statbuf.st_uid);
-
- effecid = statbuf.st_uid; /* mostly needed for return mail */
- }
- }
-