home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / tools / cleanque.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  12.3 KB  |  463 lines

  1. /* $Header: cleanque.c,v 1.6 85/04/05 13:42:13 long Exp $ */
  2. /*
  3.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  4.  *     
  5.  *
  6.  *     Copyright (C) 1979,1980,1981  University of Delaware
  7.  *     
  8.  *     Department of Electrical Engineering
  9.  *     University of Delaware
  10.  *     Newark, Delaware  19711
  11.  *
  12.  *     Phone:  (302) 738-1163
  13.  *     
  14.  *     
  15.  *     This program module was developed as part of the University
  16.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  17.  *     
  18.  *     Acquisition, use, and distribution of this module and its listings
  19.  *     are subject restricted to the terms of a license agreement.
  20.  *     Documents describing systems using this module must cite its source.
  21.  *
  22.  *     The above statements must be retained with all copies of this
  23.  *     program and may not be removed without the consent of the
  24.  *     University of Delaware.
  25.  *     
  26.  *
  27.  *     version  -1    David H. Crocker    March   1979
  28.  *     version   0    David H. Crocker    April   1980
  29.  *     version  v7    David H. Crocker    May     1981
  30.  *     version   1    David H. Crocker    October 1981
  31.  *
  32.  */
  33. #include "util.h"
  34. #include "mmdf.h"
  35. #include "msg.h"
  36. #include "adr_queue.h"
  37. #include "ch.h"
  38. #include <sys/stat.h>
  39.  
  40. /*  QUECLEAN:  Clean up the mail queue directories                      */
  41.  
  42. /*  Jul 80 Dave Crocker     noaddr, correct the 2d multcpy
  43.  *  Aug 80 Dave Crocker     fix orphaned
  44.  *  Aug 80 Dave Crocker     fix name-handling for mclean
  45.  *  Aug 81 Dave Crocker     test for chdir failures
  46.  *  Mar 83 Doug Kingston    modified to use format independent directory
  47.  *                access routines a la 4.2BSD.  (libndir.a)
  48.  */
  49.  
  50. /*#define RUNALON */
  51.  
  52. #define MINAGE  (long) (60 * 60 * 4)
  53.                   /* at least four hours old             */
  54.  
  55. extern int warntime;    /* hours to wait before notification  */
  56. extern int failtime;    /* hours to wait before returning msg */
  57. extern int errno;
  58. extern LLog msglog;
  59. LLog *logptr = &msglog;
  60.  
  61. extern char *quedfldir,
  62.         *aquedir,
  63.         *squepref,
  64.         *tquedir,
  65.         *mquedir,
  66.         *supportaddr;
  67.  
  68. DIR *quep;                     /* for reading directory entries      */
  69.  
  70. struct stat    testnode;
  71.  
  72. time_t  curtime;              /* Current time in hours              */
  73. int    elaphour;          /* Message waiting time in hours      */
  74.  
  75. char    aname[LINESIZE],
  76.     mname[LINESIZE];
  77.  
  78. int     effecid,                  /* system number of pgm/file's owner  */
  79.     callerid;                 /* who invoked me?                    */
  80.  
  81. LOCFUN ismsg(), msg_dequeue(), mn_mmdf();
  82.  
  83. /* */
  84.  
  85. main (argc, argv)          /* remove old queue files             */
  86. int       argc;
  87. char   *argv[];
  88. {
  89.     extern char *dupfpath ();
  90.     extern time_t time ();
  91.  
  92.     mmdf_init (argv[0]);
  93.     nice (-5);                 /* try to run faster, if root           */
  94.  
  95.     getwho (&callerid, &effecid); /* who am I and who is running me?    */
  96.     mn_mmdf();            /* set up effective and group id's properly */
  97.  
  98.     if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'w')
  99.     domsg = TRUE;
  100.  
  101.     time (&curtime);
  102.  
  103.     if (chdir (quedfldir) < OK || chdir (tquedir) < OK)
  104.     {
  105.     printx ("couldn't chdir to tquedir\n");
  106.     ll_err (logptr, LLOGFAT, "couldn't chdir tquedir");
  107.     exit (-1);
  108.     }
  109.  
  110.     tclean ();              /* clean out temporary files          */
  111.  
  112.     if (chdir (quedfldir) < OK)
  113.     {
  114.     printx ("couldn't chdir to quedfldir\n");
  115.     ll_log (logptr, LLOGFAT, "couldn't chdir to quedfldir");
  116.     exit (-1);
  117.     }
  118.  
  119.     mclean ();              /* get rid of orphaned text files     */
  120.  
  121.     if (chdir (quedfldir) < OK)
  122.     {
  123.     printx ("couldn't chdir to quedfldir\n");
  124.     ll_log (logptr, LLOGFAT, "couldn't chdir to quedfldir");
  125.     exit (-1);
  126.     }
  127.  
  128.     aclean ();                    /* get rid of old queued messages     */
  129. }
  130. /*  ***************  GET RID OF OLD TEMPORARY FILES  ****************  */
  131.  
  132. tclean ()              /* clean out temporary files          */
  133. {
  134.     register struct dirtype *dp;
  135.     
  136.     if ((quep = opendir (".")) == NULL)
  137.     {
  138.     printx ("couldn't open tquedir\n");
  139.     ll_log (logptr, LLOGFAT, "couldn't open tquedir");
  140.     exit (-1);
  141.     }
  142.  
  143.     while ((dp = readdir (quep)) != NULL)
  144.     if (ismsg (dp) && minage (dp->d_name))
  145.     {
  146.         printx ("removing temp file: %s\n", dp->d_name);
  147.         ll_log (logptr, LLOGGEN, "removing temp file: %s", dp->d_name);
  148.  
  149. #ifndef RUNALON
  150.         (void)  unlink (dp->d_name);
  151. #endif
  152.     }
  153.  
  154.     closedir (quep);
  155. }
  156. /*  ***************  GET RID OF ORPHANED TEXT FILES  ****************  */
  157.  
  158. mclean ()              /* get rid of orphaned text files     */
  159. {
  160.     register struct dirtype *dp;
  161.     
  162.     if ((quep = opendir (mquedir)) == NULL)
  163.     {
  164.     printx ("couldn't open quedfldir\n");
  165.     ll_log (logptr, LLOGFAT, "couldn't open quedfldir");
  166.     exit (-1);
  167.     }
  168.  
  169.     while ((dp = readdir (quep)) != NULL)
  170.     if (ismsg (dp))
  171.         mproc (dp->d_name);
  172.  
  173.     closedir (quep);
  174.     quep = (DIR *) EOF;
  175. }
  176.  
  177. mproc (filename)                /* check for & remove orphaned msgs   */
  178. char    filename[];
  179. {
  180.     (void) sprintf (mname, "%s%s", mquedir, filename);
  181.     (void) sprintf (aname, "%s%s", aquedir, filename);
  182.  
  183.     if (minage (mname) && stat (aname, &testnode) == -1)
  184.     {                             /* old & no aquedir association       */
  185.     printx ("removing old orphaned text file: %s\n", filename);
  186.     ll_log (logptr, LLOGGEN, "removing text file: %s", filename);
  187.  
  188. #ifndef RUNALON
  189.     (void)  unlink (mname);
  190. #endif
  191.     }
  192. }
  193.  
  194. /* */
  195.  
  196. minage (filename)                /* is file more than x hours old?      */
  197. char    filename[];
  198. {
  199.     if (stat (filename, &testnode) == -1)
  200.     return (FALSE);           /* doesn't really exist               */
  201.  
  202. #ifdef RUNALON
  203.     printx ("O? %s\n", filename);
  204. #endif
  205.  
  206.     return (((curtime - testnode.st_mtime) > MINAGE) ? TRUE : FALSE);
  207.                   /* two hours since modified?          */
  208. }
  209. /*  **************  GET RID OF MESSAGES IN QUEUE TOO LONG **********  */
  210.  
  211. aclean ()
  212. {
  213.     Msg  themsg;
  214.     char retadr[LINESIZE];
  215.     register struct dirtype *dp;
  216.  
  217.     if ((quep = opendir (aquedir)) == NULL)
  218.         err_abrt (RP_FOPN, "can't open address queue");
  219.  
  220.     themsg.mg_null = '\0';
  221.     while ((dp = readdir (quep)) != NULL)
  222.     if (ismsg (dp))
  223.     {
  224.                   /* get queue entry name (msg name)   */
  225.         (void) strcpy (themsg.mg_mname, dp->d_name);
  226.         if (mq_rinit ((Chan *) 0, &themsg, retadr) != OK)
  227.         continue;
  228.         elaphour = (int) ((curtime - themsg.mg_time) / (time_t) 3600);
  229. #ifdef DEBUG
  230.         ll_log (logptr, LLOGFTR,
  231.                 "%s (%d hrs)", themsg.mg_mname, elaphour);
  232. #endif
  233.         if (elaphour > warntime) /* message is old                   */
  234.         {
  235.         if (elaphour > failtime)
  236.         {
  237.                     /* old enough to return?            */
  238.             doreturn (&themsg, retadr);
  239.             deque (&themsg);
  240.         }
  241.         else if (!msg_warned(themsg.mg_stat))
  242.             dowarn (&themsg, retadr);
  243.         }
  244.         mq_rkill (OK);
  245.     }
  246.  
  247.     closedir (quep);
  248.     quep = (DIR *) EOF;
  249. }
  250.  
  251. /* */
  252.  
  253. LOCFUN
  254.     ismsg (theentry)         /* a processable message?             */
  255.     register struct dirtype *theentry;
  256. {
  257. #ifdef DEBUG
  258.     ll_log (logptr, LLOGFTR, "ovr_ismsg (name='%s')",
  259.             theentry -> d_name);
  260. #endif
  261.  
  262. /*  valid message:  entry allocated & name begins with "msg." */
  263.  
  264.     return ((
  265. #ifdef BSDDIRECT
  266.     theentry -> d_namlen < MSGNSIZE
  267. #else
  268.     (strlen(theentry->d_name) < MSGNSIZE)
  269. #endif
  270.         && equal (theentry -> d_name, "msg.", 4)) ? TRUE : FALSE);
  271. }
  272.  
  273. deque (themsg)
  274.     Msg *themsg;
  275. {
  276.     struct adr_struct theadr;
  277.     char curque[ADDRSIZE];
  278.  
  279. #ifdef DEBUG
  280.     ll_log (logptr, LLOGBTR, "deque");
  281. #endif
  282.  
  283.     curque[0] = '\0';   /* no queue in effect */
  284.  
  285.     mq_setpos (0L);    /* start at the beginning of the queue */
  286.     while (mq_radr (&theadr) == OK)
  287.     {
  288. #ifdef DEBUG
  289.     ll_log (logptr, LLOGFTR,
  290.             "(%c)%s:%s", theadr.adr_delv, theadr.adr_que, curque);
  291. #endif
  292.         /*
  293.          *  We have to dequeue from every queue since the return
  294.          *  function already has marked all the addresses as "DONE".
  295.          *  The msg_dequeue function was modified to ignore ENOENT
  296.          *  so if the file is already gone, it is not an error.
  297.          */
  298.     if (!lexequ (curque, theadr.adr_que))
  299.     {
  300.         (void) strcpy (curque, theadr.adr_que);
  301.         msg_dequeue (theadr.adr_que, themsg);
  302.     }
  303.     }
  304.     msg_dequeue ((char *) 0, themsg);
  305. }
  306. /* */
  307.  
  308. LOCFUN
  309.     msg_dequeue (theque, themsg) /* remove message from queue          */
  310.         char *theque;
  311.         Msg *themsg;
  312. {
  313.     char thename[LINESIZE];
  314. #ifdef DEBUG
  315.     ll_log (logptr, LLOGBTR, "msg_deque (%s,%s)", 
  316.         (theque == (char *) 0) ? "(Base entry)" : theque,
  317.         themsg -> mg_mname);
  318. #endif
  319. #ifdef RUNALON
  320.     return;
  321. #endif
  322.  
  323.     if (theque == (char *) 0)
  324.         (void) sprintf (thename, "%s%s", aquedir, themsg -> mg_mname);
  325.     else
  326.     (void) sprintf (thename, "%s%s/%s",
  327.             squepref, theque, themsg -> mg_mname);
  328.  
  329.     if (unlink (thename) < OK && errno != ENOENT) {
  330.      /* this is real queue handle  */
  331.      ll_err (logptr, LLOGTMP, "Problem unlinking '%s' address: %s",
  332.             themsg -> mg_mname, thename);
  333.     }
  334.  
  335.     if (theque == (char *) 0)
  336.     {                  /* get rid of ALL the message */
  337.     (void) sprintf (thename, "%s%s", mquedir, themsg -> mg_mname);
  338.     if (unlink (thename) < OK) /* the text is just "baggage"         */
  339.         ll_err (logptr, LLOGTMP, "Problem unlinking %s text: '%s'",
  340.             themsg -> mg_mname, thename);
  341.     }
  342. }
  343. /* */
  344.  
  345. dowarn (themsg, retadr)
  346.     Msg *themsg;
  347.     char retadr[];
  348. {
  349. #ifdef DEBUG
  350.     ll_log (logptr, LLOGBTR, "dowarn (%s, %s)", themsg -> mg_mname, retadr);
  351. #endif
  352.  
  353.     printx ("%s:  delivery overdue; ", themsg -> mg_mname);
  354.     (void) fflush (stdout);
  355.  
  356.     if (msg_nowarn (themsg -> mg_stat)) {
  357.     printx ("warning not wanted\n");
  358.     }
  359.     else if (rtn_warn (themsg, retadr) == OK)
  360.     {                     /* flag as already warned               */
  361.     printx ("warning sent\n");
  362.     ll_log (logptr, LLOGGEN, "warn *** Time warning (%s, %s)",
  363.             themsg -> mg_mname, retadr);
  364.     }
  365.     else
  366.     {
  367.     printx ("couldn't send warning\n");
  368.     ll_err (logptr, LLOGTMP, "warn *** Couldn't time warn (%s, %s)",
  369.             themsg -> mg_mname, retadr);
  370.     }
  371.     (void) fflush (stdout);
  372.  
  373.     mq_rwarn ();
  374. }
  375.  
  376. doreturn (themsg, retadr)
  377.     Msg *themsg;
  378.     char retadr[];
  379. {
  380. #ifdef DEBUG
  381.     ll_log (logptr, LLOGBTR, "doreturn (%s, %s)", themsg -> mg_mname, retadr);
  382. #endif
  383.  
  384.     printx ("%s:  not delivered in time; waiting %d hrs;", themsg -> mg_mname, elaphour);
  385.     (void) fflush (stdout);
  386.     if (msg_noret (themsg -> mg_stat)) {
  387.     printx (" error return not wanted\n");
  388.     }    
  389.     else if (rtn_time (themsg, retadr) == OK)
  390.     {                         /* dequeue if couldn't notify   */
  391.     printx (" returned\n");
  392.     (void) fflush (stdout);
  393.     ll_log (logptr, LLOGTMP, "ret *** Timeout return (%s, %s)",
  394.             themsg -> mg_mname, retadr);
  395.     }
  396.     else
  397.     {                         /* dequeue if couldn't notify   */
  398.     char orphanage[ADDRSIZE];
  399.  
  400.     (void) sprintf (orphanage, "Orphanage <%s>", supportaddr);
  401.     printx (" couldn't return,\ntrying orphanage...");
  402.     (void) fflush (stdout);
  403.     if (rtn_time (themsg, orphanage) == OK)
  404.     {
  405.         printx (" returned to orphanage.\n");
  406.         (void) fflush (stdout);
  407.     }
  408.     else
  409.     {
  410.         ll_err (logptr, LLOGTMP, "ret *** Timeout couldn't return (%s,%s)",
  411.             themsg -> mg_mname, retadr);
  412.         dead_letter (themsg->mg_mname, "Timeout on delivery");
  413.     }
  414.     }
  415. }
  416.  
  417.  
  418. /* */
  419.  
  420. LOCFUN
  421.         mn_mmdf ()          /* setuid to mmdf: bypass being root  */
  422. {                  /* get sys id for mmdf; setuid to it  */
  423.     extern char *pathsubmit;     /* submit command file name           */
  424.     extern char *cmddfldir;      /* directory w/mmdf commands          */
  425.     char    temppath[LINESIZE];
  426.     struct stat    statbuf;
  427.  
  428. #ifdef DEBUG
  429.     ll_log (logptr, LLOGPTR, "mn_mmdf(); effec==%d",
  430.         effecid );
  431. #endif
  432.  
  433. /*  the following is a little strange, doing a stat on the object
  434.  *  file, because setuid-on-execute does not work when the caller
  435.  *  is root, as will happen when this is started by the rc file.
  436.  *  hence, the effective id, from a getuid, will show root & not mmdf.
  437.  *
  438.  *  the goal is to have this process be name-independent of the caller,
  439.  *  so that returned mail comes from mmdf and not the invoker.
  440.  *
  441.  *  in pickup mode, the id of the caller has to be retained, since
  442.  *  pobox channels use that to determine access rights to mail.
  443.  *
  444.  *  All sets gid to mmdf's gid  --  <DPK@BRL>
  445.  */
  446.  
  447.     if (effecid == 0)
  448.     {
  449.     getfpath (pathsubmit, cmddfldir, temppath);
  450.  
  451.     if (stat (temppath, &statbuf) < OK)
  452.         err_abrt (RP_LIO, "Unable to stat %s", temppath);
  453.                   /* use "submit" to get mmdf id        */
  454.  
  455.     if (setgid (statbuf.st_gid) == NOTOK)
  456.         err_abrt (RP_LIO, "Can't setgid to mmdf (%d)", statbuf.st_gid);
  457.     if (setuid (statbuf.st_uid) == NOTOK)
  458.         err_abrt (RP_LIO, "Can't setuid to mmdf (%d)", statbuf.st_uid);
  459.  
  460.     effecid = statbuf.st_uid; /* mostly needed for return mail      */
  461.     }
  462. }
  463.