home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Src / submit / submit_que.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  7.4 KB  |  360 lines

  1. /* submit_que.c: store messages in the queue */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_que.c,v 6.0 1991/12/18 20:28:02 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_que.c,v 6.0 1991/12/18 20:28:02 jpo Rel $
  9.  *
  10.  * $Log: submit_que.c,v $
  11.  * Revision 6.0  1991/12/18  20:28:02  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include        "head.h"
  19. #include        "prm.h"
  20. #include        "q.h"
  21. #include     "adr.h"
  22. #include        <fcntl.h>
  23. #if defined(sun) || defined(SYS5)
  24. #ifdef vfork
  25. #undef vfork
  26. #endif
  27. #include    <unistd.h>
  28. #endif
  29. #include     "sys.file.h"
  30. #include        <sys/time.h>
  31.  
  32.  
  33. extern UTC      time_t2utc();
  34. extern void    err_abrt();
  35. extern long     msg_size;
  36. extern char     *quedfldir;
  37. extern char     *aquefile;              /* addr file */
  38. extern char    *bquedir;               /* Q/msg/msg.XXX/base dir */
  39. extern int    queue_depth;
  40. extern int    queue_fanout;
  41. extern int    errno;
  42. extern int    disk_blocks, disk_percent;
  43.  
  44. /* -- globals -- */
  45. char            *msg_basedir;           /* full pathname to bquedir */
  46. char        *msg_unique;            /* unique-part of Q/msg file name */
  47. char        msg_fullpath[MAXPATHLENGTH]; /* full pathname to msg */
  48. static char    *ad_file;            /* the (temp) addr file */
  49.  
  50.  
  51. /* -- static variables -- */
  52. static FILE     *ad_ffp;                /* file pointer to address file */
  53.  
  54. /* -- local routines -- */
  55. void        clear_q();
  56. int        move_q();
  57. int        winit_q();
  58. int        write_q();
  59. static int    make_temp();
  60. static void make_hier_queue ();
  61. static void make_missing_dirs ();
  62.  
  63.  
  64.  
  65. /* ---------------------  Begin  Routines  -------------------------------- */
  66.  
  67.  
  68.  
  69.  
  70. /* -- initialise system to write a message into the queue. -- */
  71. int winit_q(rp)
  72. RP_Buf *rp;
  73. {
  74.     char            buf[MAXPATHLENGTH];
  75.     char        addition[BUFSIZ];
  76.  
  77.     PP_TRACE (("submit/winit_q()"));
  78.  
  79.     (void) strcpy (msg_fullpath, quedfldir);
  80.     (void) strcat (msg_fullpath, "/");
  81.     msg_unique = msg_fullpath + strlen (msg_fullpath);
  82.     if (queue_depth > 0)
  83.         make_hier_queue (addition);
  84.     if (make_temp (msg_unique, queue_depth > 0 ? addition : NULLCP,
  85.                msg_fullpath) == NOTOK)
  86.         return rplose (rp, RP_FCRT, "Can't create a unique Q file");
  87.  
  88.     if (ad_file)
  89.         free (ad_file);
  90.     (void) sprintf (buf, "%s/%s.X", msg_fullpath, aquefile);
  91.     ad_file = strdup (buf);
  92.  
  93.     if ((ad_ffp = fopen (ad_file, "w")) == NULL)
  94.         rplose (rp, RP_FOPN, "Can't access text Q file %s", buf);
  95.  
  96.     (void) sprintf (buf, "%s/%s", msg_fullpath, bquedir);
  97.     msg_basedir = strdup (buf);
  98.  
  99.     if (fdiskfull (fileno(ad_ffp), disk_blocks, disk_percent) == NOTOK) {
  100.         (void) fclose (ad_ffp);
  101.         return rplose (rp, RP_FIO, "Disk usgae limit exceeded");
  102.     }
  103.     return RP_OK;
  104. }
  105.  
  106. int move_q (rp)
  107. RP_Buf *rp;
  108. {
  109.     char    tfile[MAXPATHLENGTH];
  110.  
  111.     (void) sprintf  (tfile, "%s/%s", msg_fullpath, aquefile);
  112.     PP_TRACE (("Renames %s to %s", ad_file, tfile));
  113.     if (rename (ad_file, tfile) == NOTOK)
  114.         return rplose (rp, RP_FCRT, "Can't rename %s to %s",
  115.                    ad_file, tfile);
  116.     free (ad_file);
  117.     ad_file = NULLCP;
  118.     return RP_OK;
  119. }
  120.  
  121.  
  122.  
  123.  
  124. int write_q (qp, pr, rp)
  125. register Q_struct               *qp;
  126. register struct prm_vars        *pr;
  127. RP_Buf *rp;
  128. {
  129.     int                     retval;
  130.     ADDR                    *ap;
  131.  
  132.     PP_TRACE (("submit/write_q (qp,pr)"));
  133.  
  134.     if (qp->msgsize == NULL)
  135.         qp->msgsize = msg_size;
  136.  
  137.     if (qp->queuetime == 0)
  138.         qp->queuetime = utcnow ();
  139.  
  140.     if (pr -> prm_opts)
  141.         pr -> prm_opts = PRM_NONE;
  142.     if (pr -> prm_passwd) {
  143.         free (pr -> prm_passwd);
  144.         pr -> prm_passwd = NULLCP;
  145.     }
  146.  
  147.     retval = wr_prm (pr, ad_ffp);
  148.     if (rp_isbad (retval))
  149.         goto bad;
  150.  
  151.     retval = wr_q (qp, ad_ffp);
  152.     if (rp_isbad (retval))
  153.         goto bad;
  154.  
  155.     retval = wr_adr (qp->Oaddress, ad_ffp, AD_ORIGINATOR);
  156.     if (rp_isbad (retval))
  157.         goto bad;
  158.  
  159.     for (ap = qp -> Raddress; ap; ap = ap -> ad_next) {
  160.         retval = wr_adr (ap, ad_ffp, AD_RECIPIENT);
  161.         if (rp_isbad (retval))
  162.             goto bad;
  163.     }
  164.  
  165.     if (check_close (ad_ffp) == NOTOK)
  166.         err_abrt (RP_FIO, "Error writing address file");
  167.     ad_ffp = NULLFILE;
  168.     return RP_OK;
  169.  
  170. bad:
  171.     return rplose (rp, RP_FIO, "Error writing to q file");
  172. }
  173.  
  174.  
  175.  
  176.  
  177. /* -- in case of error, zap all the work thats been done. -- */
  178. void clear_q()
  179. {
  180.     PP_TRACE (("clear_q ()"));
  181.     (void) txt_tend();
  182.     if (ad_ffp != NULLFILE) { /* address file */
  183.         (void) fclose (ad_ffp);
  184.         ad_ffp = NULLFILE;
  185.     }
  186.     if (ad_file) {
  187.         (void) recrm (msg_fullpath);
  188.         if(rmdir (msg_fullpath))
  189.             PP_SLOG (LLOG_EXCEPTIONS, msg_fullpath,
  190.                  ("failed to remove directory"));
  191.         else
  192.             PP_NOTICE(("Cleanup - zapped %s", msg_fullpath));
  193.     }
  194. }
  195.  
  196.  
  197.  
  198.  
  199. /* ---------------------  Static  Routines  ------------------------------- */
  200.  
  201. static int    mypid = 0;
  202.  
  203. static void make_missing_dirs (base, seper)
  204. char    *base;
  205. char    *seper;
  206. {
  207.     char    buf[BUFSIZ];
  208.     char    *p;
  209.  
  210.     (void) strcpy (buf, base);
  211.     p = buf + strlen (buf);
  212.     (void) strcpy (p, seper);
  213.  
  214.     while ((p = index(p, '/')) != NULL) {
  215.         *p = '\0';
  216.         if (mkdir(buf, 0777) == NOTOK && errno != EEXIST) {
  217.             *p = '/';
  218.             err_abrt (RP_FIO, "Can't create directory %s",
  219.                   buf);
  220.         }
  221.         *p = '/';
  222.         p++;
  223.     }
  224. }
  225. #ifndef BSD42
  226. #define random rand
  227. #define srandom srand
  228. #endif
  229.  
  230. static void make_hier_queue (buf)
  231. char *buf;
  232. {
  233.     char *p;
  234.     static int init = 0;
  235.     int i;
  236.  
  237.     if (init == 0) {
  238.         if (mypid == 0)
  239.             mypid = getpid ();
  240.         srandom (mypid);
  241.         init = 1;
  242.     }
  243.  
  244.     p = buf;
  245.     for (i = 0; i < queue_depth; i++) {
  246.         (void) sprintf (p, "%d/", random() % queue_fanout);
  247.         p += strlen(p);
  248.     }
  249. }
  250.  
  251. /*
  252.  * mktemp gives up too easily - this ones goes on forever
  253.  * I think we'll run out of inodes long before this fails...
  254.  */
  255.  
  256.  
  257. static int make_temp (unique, seper, base)
  258. char    *base;
  259. char    *seper;
  260. char    *unique;
  261. {
  262.     static long     tries = 0;
  263.     int     made_dirs = 0;
  264.  
  265.     if (mypid == 0) mypid = getpid ();
  266.  
  267.     for (; tries < 32000; tries ++) {
  268.         if (seper)
  269.             (void) sprintf (unique, "%smsg.%05d-%d",
  270.                     seper, mypid, tries);
  271.         else
  272.             (void) sprintf (unique, "msg.%05d-%d",
  273.                     mypid, tries);
  274.         
  275.         if (mkdir (base, 0777) == OK)
  276.             return OK;
  277.         else if (seper && !made_dirs) {
  278.             tries --; /* try again after we created missing dirs */
  279.             made_dirs = 1;
  280.             unique[0] = '\0';
  281.             make_missing_dirs (base, seper);
  282.         }
  283.             
  284.     }
  285.     return NOTOK;
  286. }
  287.  
  288. static struct matrix_tbl {
  289.     char    *name;
  290.     char    *key;
  291.     char    *directory;
  292.     int    no;
  293.     struct matrix_tbl *m_next;
  294. } *MTbl;
  295.  
  296. static char *do_table (str, name)
  297. char *str, *name;
  298. {
  299.     struct matrix_tbl **mp, *m;
  300.     int maxkeyno = 1;
  301.     char buf[BUFSIZ];
  302.  
  303.     for (mp = &MTbl; 
  304.          (m = *mp) != (struct matrix_tbl *) NULL; 
  305.          mp = &(*mp) -> m_next) {
  306.         if (strcmp(m -> name, str) == 0)
  307.             return strdup(m -> directory);
  308.         else if (strcmp (m -> key, name) == 0) {
  309.             if (m -> no >= maxkeyno)
  310.                 maxkeyno = m -> no + 1;
  311.         }
  312.     }
  313.     m = *mp = (struct matrix_tbl *) smalloc(sizeof **mp);
  314.     m -> name = strdup (str);
  315.     m -> key = strdup(name);
  316.     m -> no = maxkeyno;
  317.     (void) sprintf (buf, "%s.%d", name, maxkeyno);
  318.     m -> directory = strdup (buf);
  319.     m -> m_next = NULL;
  320.     return strdup (m -> directory);
  321. }
  322.  
  323. void free_table (mp)
  324. struct matrix_tbl *mp;
  325. {
  326.     if (mp == (struct matrix_tbl *) NULL)
  327.         return;
  328.     if (mp -> name) free (mp -> name);
  329.     if (mp -> key) free (mp -> key);
  330.     if (mp -> directory) free (mp -> directory);
  331.     if (mp -> m_next) free_table(mp -> m_next);
  332.     free ((char *)mp);
  333. }
  334.  
  335. do_dirs (ap)
  336. ADDR *ap;
  337. {
  338.     char    buf[BUFSIZ];
  339.     LIST_RCHAN *fmt;
  340.  
  341.     buf[0] = 0;
  342.     for (fmt = ap -> ad_fmtchan; fmt; fmt = fmt -> li_next) {
  343.         (void) strcat (buf, "/");
  344.         (void) strcat (buf, fmt -> li_chan -> ch_name);
  345.         fmt -> li_dir = do_table (buf, fmt -> li_chan -> ch_name);
  346.     }
  347. }
  348.  
  349. setup_directories (qp)
  350. Q_struct *qp;
  351. {
  352.     ADDR *ap;
  353.     do_dirs (qp -> Oaddress);
  354.     for (ap = qp -> Raddress; ap; ap = ap -> ad_next)
  355.         do_dirs (ap);
  356.  
  357.     free_table (MTbl);
  358.     MTbl = NULL;
  359. }
  360.