home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / fax-3.2.1 / cmd / faxspooler / process.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-31  |  12.0 KB  |  523 lines

  1. /*
  2.   This file is part of the NetFax system.
  3.  
  4.   (c) Copyright 1989 by David M. Siegel. 
  5.       All rights reserved.
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation.
  10.  
  11.     This program is distributed in the hope that it will be useful, 
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <malloc.h>
  23. #include <unistd.h>
  24. #include <sys/param.h>
  25. #include <sys/wait.h>
  26. #include <sys/types.h>
  27. #include <sys/socket.h>
  28.  
  29. #include "../../lib/libutil/dispatch.h"
  30. #include "../../lib/libutil/reap.h"
  31. #include "../../lib/libfax/libfax.h"
  32. #include "spooler.h"
  33. #include "queue_entry.h"
  34. #include "queue.h"
  35. #include "send.h"
  36. #include "receive.h"
  37. #include "jobs.h"
  38. #include "process.h"
  39.  
  40. /*
  41.  * Mail a notification report to the user listed in the queue entry.
  42.  * This function should only be called if the notification bit in
  43.  * the flags field has been set.
  44.  */
  45. static void mail_notification(qe)
  46.      QueueEntry *qe;
  47. {
  48.     char cmd[256];
  49.     FILE *fp;
  50.     NODE *node = NULL;
  51.     Recip *r;
  52.  
  53.     sprintf(cmd, "/usr/ucb/Mail -s \"fax delivery report\" %s", qe->user);
  54.     if ((fp = popen(cmd, "w")) == NULL) {
  55.     log(L_ALERT, "can't open mail program: %m");
  56.     return;
  57.     }
  58.  
  59.     fprintf(fp, "Fax job was submitted by %s.\n", qe->user);
  60.     fprintf(fp, "Job had a total of %d pages.\n\n", qe->pages);
  61.  
  62.     while ((r = (Recip *)list_next(qe->recip_list, &node)) != NULL) {
  63.     fprintf(fp, "Recipient %s: ", r->phone);
  64.     if (r->status == SEND_STATUS_SENT)
  65.       fprintf(fp, "sent in %d seconds.\n", r->total_time);
  66.     else
  67.       fprintf(fp, "delivery failed.\n");
  68.     }
  69.  
  70.     pclose(fp);
  71. }
  72.  
  73. typedef enum {
  74.     RECIP_READY,
  75.     RECIP_NOT_READY,
  76.     RECIP_DONE,
  77. } recip_stat;
  78.  
  79. /*
  80.  * Determine if a recipient is ready to be run.
  81.  *
  82.  * Return codes:
  83.  *    RECIP_READY    ok to send to this recipient
  84.  *    RECIP_NOT_READY    haven't reached retry time
  85.  *    RECIP_DONE    all done with this recipient
  86.  */
  87. static int is_recip_ready(sd, r, now)
  88.      spooler_data *sd;
  89.      Recip *r;
  90.      time_t now;
  91. {
  92.     /*
  93.      * Initialize delivery time, if necessary.
  94.      */
  95.     if (r->time_first == 0)
  96.       r->time_first = now;
  97.  
  98.     /*
  99.      * Has the fax been sent to this recipient yet?
  100.      */
  101.     if (r->status == SEND_STATUS_SENT || r->status == SEND_STATUS_GIVEUP)
  102.       return (RECIP_DONE);
  103.  
  104.     /*
  105.      * Make sure the job hasn't timed out, and that the
  106.      * minimum retry interval has elapsed.  If so, then
  107.      * make a delivery attempt.
  108.      */
  109.     if (now - r->time_first > sd->max_delivery_time) {
  110.     /*
  111.      * We've exceeded the max retry interval.
  112.      */
  113.     log(L_INFO, "giving up on delivery to %s", r->phone);
  114.     r->status = SEND_STATUS_GIVEUP;
  115.     return (RECIP_DONE);
  116.     } else if (now - r->time_last > sd->min_retry_wait) {
  117.     /*
  118.      * Ready to try sending the job (again).
  119.      */
  120.     return (RECIP_READY);
  121.     } else
  122.       return (RECIP_NOT_READY);
  123. }
  124.  
  125. static void send_log(sd, qe, r)
  126.      spooler_data *sd;
  127.      QueueEntry *qe;
  128.      Recip *r;
  129. {
  130.     char log_file[MAXPATHLEN];
  131.     FILE *log_fp;
  132.  
  133.     sprintf(log_file, "%s/.log", sd->out_qdir);
  134.     if ((log_fp = fopen(log_file, "a")) == NULL)
  135.       return;
  136.  
  137.     fprintf(log_fp, "%s sent a %d page fax to %s (%d seconds)\n",
  138.         qe->user, qe->pages, r->phone, r->total_time);
  139.  
  140.     fclose(log_fp);
  141. }
  142.  
  143. typedef struct _recip_exit_data {
  144.     spooler_data *sd;
  145.     Recip *r;
  146.     QueueEntry *qe;
  147.     int result_fds[2];
  148.     int fm;
  149. } recip_exit_data;
  150.  
  151. /* ARGSUSED */
  152. static int recip_exit_handler(pid, status, data)
  153.      int pid;
  154.      int status;
  155.      char *data;
  156. {
  157.     recip_exit_data *d = (recip_exit_data *)data;
  158.     spooler_data *sd;
  159.  
  160.     /*
  161.      * We don't care about stopped children.
  162.      */
  163.     if (WIFSTOPPED(status))
  164.       return (0);
  165.  
  166.     /*
  167.      * Only perform the read if the child really exited.
  168.      */
  169.     if (WIFEXITED(status)) {
  170.     int rc = WEXITSTATUS(status);
  171.     
  172.     /*
  173.      * Copy back the recip info.
  174.      */
  175.     read(d->result_fds[1], (char *)d->r, sizeof(Recip));
  176.  
  177.     /*
  178.      * Log the result, if it was send.
  179.      */
  180.     if (d->r->status == SEND_STATUS_SENT)
  181.       send_log(d->sd, d->qe, d->r);
  182.  
  183.     log(L_INFO, "child exited with rc=%d, status=%d", rc, d->r->status);
  184.     } else {
  185.     d->r->status = SEND_STATUS_FAILED;
  186.     log(L_ALERT, "child didn't exit properly");
  187.     }
  188.  
  189.     /*
  190.      * Indicate the modem is now free.
  191.      */
  192.     sd = d->sd;
  193.     sd->fm_busy[d->fm] = FALSE;
  194.     recv_enable(sd, d->fm);
  195.  
  196.     /*
  197.      * We are no longer running this queue entry.
  198.      */
  199.     d->qe->flags &= ~QUEUE_F_RUNNING;
  200.  
  201.     /*
  202.      * Close things up.
  203.      */
  204.     close(d->result_fds[0]);
  205.     close(d->result_fds[1]);
  206.     cfree(d);
  207.  
  208.     /*
  209.      * Run the queue, for good measures.
  210.      */
  211.     run_queue(sd);
  212.  
  213.     return (0);
  214. }
  215.  
  216. /*
  217.  * Attempt to send a fax to the given recipient.  This spawns a new
  218.  * sending process, which actually does the sending work.  The
  219.  * send process write the recip and faxmodem struct to a file,
  220.  * which the parent will read in when the job complete.  This is
  221.  * the easiest way to pass the status information back and forth.
  222.  *
  223.  * Return codes:
  224.  *    0    fax is being sent
  225.  *     -1    sending fork failed
  226.  */
  227. static int run_recip(sd, qe, r, qdir, fmp, fm)
  228.      spooler_data *sd;
  229.      QueueEntry *qe;
  230.      Recip *r;
  231.      char *qdir;
  232.      FaxModem *fmp;
  233.      int fm;
  234. {
  235.     recip_exit_data *d;
  236.  
  237.     log(L_INFO, "sending to %s", r->phone);
  238.  
  239.     /*
  240.      * Disable incoming faxes from this modem.
  241.      */
  242.     recv_disable(sd, fm);
  243.  
  244.     /*
  245.      * Data we pass to the fork reaper.
  246.      */
  247.     if ((d = (recip_exit_data *)calloc(1, sizeof(recip_exit_data))) == NULL) {
  248.     log(L_ALERT, "calloc of exit data failed: %m");
  249.     return (-1);
  250.     }
  251.     d->qe = qe;
  252.     d->r = r;
  253.     d->fm = fm;
  254.     d->sd = sd;
  255.  
  256.     /*
  257.      * Setup the communication link.
  258.      */
  259.     if (socketpair(AF_UNIX, SOCK_STREAM, 0, d->result_fds) < 0) {
  260.     log(L_ALERT, "can't create socket pair: %m");
  261.     recv_enable(sd, fm);
  262.     cfree(d);
  263.     return (-1);
  264.     }
  265.  
  266.     /*
  267.      * Indicate that we are currently sending this fax.
  268.      */
  269.     r->status = SEND_STATUS_SENDING;
  270.  
  271.     /*
  272.      * Fork off the child process to handling sending this fax.
  273.      */
  274.     switch(reap_fork(recip_exit_handler, (char *)d)) {
  275.       case -1:
  276.     /* error */
  277.     log(L_ALERT, "spawn of sending agent failed: %m");
  278.     recv_enable(sd, fm);
  279.     close(d->result_fds[0]);
  280.     close(d->result_fds[1]);
  281.     cfree(d);
  282.     return (-1);
  283.       case 0:
  284.     /* child */
  285.     break;
  286.       default:
  287.     /* parent */
  288.     qe->flags |= QUEUE_F_RUNNING;
  289.     return (0);
  290.     }
  291.     
  292.     /*
  293.      * We are now in a child process. Start sending the fax. 
  294.      * Write return status information down the socketpair
  295.      * pipe.  Return 0 to indicate we can read result.
  296.      */
  297.     if (send_fax(fmp, r, qdir, qe->file, qe->pages) == 0) {
  298.     r->attempts++;
  299.     if (r->status != SEND_STATUS_SENT) {
  300.         log(L_INFO, "unable to send fax to %s", r->phone);
  301.     }
  302.     }
  303.     write(d->result_fds[0], r, sizeof(Recip));
  304.  
  305.     /*
  306.      * Resync the modem, just in case.
  307.      */
  308.     if (faxmodem_sync(&sd->fmp[d->fm], FAXMODEM_SYNC_TRIES) < 0)
  309.       log(L_EMERG, "can't resync to the modem");
  310.  
  311.     /*
  312.      * All done!
  313.      */
  314.     exit (0);
  315.     
  316.     /* we never get here, but this keeps lint happy */
  317.     return (0);
  318. }
  319.  
  320. /*
  321.  * Delete qe from the queue q, along with all the associated
  322.  * queue files.  What's the best thing to do if the delete fails?
  323.  *
  324.  * Return codes:
  325.  *    0    delete was ok
  326.  *     -1    delete failed
  327.  */
  328. static int delete_job(q, qe, qdir)
  329.      LIST *q;
  330.      QueueEntry *qe;
  331.      char *qdir;
  332. {
  333.     log(L_INFO, "deleting job %s from %s", qe->file, qe->user);
  334.  
  335.     if (qe->flags & QUEUE_F_EMAIL)
  336.       mail_notification(qe);
  337.  
  338.     queue_entry_delete_files(qe->file, qdir);
  339.  
  340.     list_delete(q, (char *)qe);
  341.  
  342.     return (0);
  343. }
  344.  
  345. static int get_modem(sd)
  346.      spooler_data *sd;
  347. {
  348.     int fm;
  349.     
  350.     /*
  351.      * Is a modem free?
  352.      */
  353.     for (fm = 0; fm < sd->numb_fm; fm++)
  354.       if (!sd->fm_busy[fm])
  355.     return (fm);
  356.  
  357.     return (-1);
  358. }
  359.  
  360. /*
  361.  * Run the queue.  This routine invokes the sending routine on
  362.  * any faxes outstanding in the queue that are ready.  The routine
  363.  * maintains state, and is invoked when jobs finish, and by a 
  364.  * dispatch timer.
  365.  *
  366.  * Return codes:
  367.  *    0    no queue entries worked on
  368.  *     -1    failure
  369.  */
  370. int run_queue(sd)
  371.      spooler_data *sd;
  372. {
  373.     int wrapped = FALSE;
  374.  
  375.     /*
  376.      * See if we can get some new work, if not just return.
  377.      */
  378.     if (sd->qe == NULL)
  379.       if ((sd->qe = (QueueEntry *)list_next(sd->q, &sd->q_node)) == NULL)
  380.     return (0);
  381.  
  382.     /*
  383.      * Scan all recipients in the queue, and invoke the
  384.      * sending routine on any that have not yet received
  385.      * the fax.
  386.      */
  387.     for (;;) {
  388.     time_t now = time(0);
  389.     int fm = get_modem(sd);
  390.  
  391.     /*
  392.      * Assume we were left on the last recipient processed,
  393.      * move on to the next one.  If we hit the last one,
  394.      * move to the next queue entry.
  395.      */
  396.     if ((sd->r = (Recip *)list_next(sd->qe->recip_list, &sd->r_node))
  397.         == NULL) {
  398.         QueueEntry *qe_last = sd->qe;
  399.         /*
  400.          * Carefully delete this queue entry if no recipients are
  401.          * left in the entry.
  402.          */
  403.         sd->qe = (QueueEntry *)list_next(sd->q, &sd->q_node);
  404.         /*
  405.          * Only do the delete if we are not running any of
  406.          * the recips, of course.
  407.          */
  408.         if (!(qe_last->flags & QUEUE_F_RUNNING) && sd->recips_left == 0)
  409.           delete_job(sd->q, qe_last, sd->out_qdir);
  410.         else
  411.           queue_entry_write(qe_last, sd->out_qdir);
  412.         /*
  413.          * If the queue has emptied out, then we are all done.
  414.          */
  415.         if (list_length(sd->q) == 0)
  416.           return (0);
  417.         /*
  418.          * Have we wrapped around the queue?  If so, start from the top.
  419.          */
  420.         if (sd->qe == NULL) {
  421.         if (wrapped)
  422.           return (0);
  423.         else
  424.           wrapped = TRUE;
  425.         sd->q_node = NULL;
  426.         sd->qe = (QueueEntry *)list_next(sd->q, &sd->q_node);
  427.         }
  428.         /*
  429.          * Get the first receipient in the queue entry.
  430.          */
  431.         sd->r_node = NULL;
  432.         sd->r = (Recip *)list_next(sd->qe->recip_list, &sd->r_node);
  433.         sd->recips_left = 0;
  434.     }
  435.  
  436.     /*
  437.      * At this point we've got a new recipient to consider,
  438.      * see if its ready for some work.
  439.      */
  440.     if (!(sd->qe->flags & QUEUE_F_DELETED)) {
  441.         switch (is_recip_ready(sd, sd->r, now)) {
  442.           case RECIP_READY:
  443.         sd->recips_left++;
  444.         /*
  445.          * Run job only if we have a modem.
  446.          */
  447.         if (fm >= 0) {
  448.             sd->r->time_last = now;
  449.             if (run_recip(sd, sd->qe, sd->r, sd->out_qdir,
  450.                   &sd->fmp[fm], fm) == 0)
  451.               sd->fm_busy[fm] = TRUE;
  452.         }
  453.         break;
  454.           case RECIP_NOT_READY:
  455.         sd->recips_left++;
  456.         break;
  457.           case RECIP_DONE:
  458.         break;
  459.         }
  460.     }
  461.     }
  462. }
  463.  
  464. /*
  465.  * This is this the main work function.  It periodically scans
  466.  * the queue for new work.  Otherwise, it runs the queue and
  467.  * checks for incoming faxes.  It is passed an initial queue.
  468.  */
  469. int process_queue(out_qdir, in_qdir, in_email, fmp, numb_fm, 
  470.           max_delivery_time, min_retry_wait)
  471.      char *out_qdir;
  472.      char *in_qdir;
  473.      char *in_email;
  474.      FaxModem *fmp;
  475.      int numb_fm;
  476.      int max_delivery_time;
  477.      int min_retry_wait;
  478. {
  479.     spooler_data *sd;
  480.  
  481.     sd = (spooler_data *)calloc(1, sizeof(spooler_data));
  482.  
  483.     sd->out_qdir = out_qdir;
  484.     sd->in_qdir = in_qdir;
  485.     sd->in_email = in_email;
  486.     sd->fmp = fmp;
  487.     sd->numb_fm = numb_fm;
  488.     sd->fm_busy = (int *)calloc(numb_fm, sizeof(int));
  489.     sd->max_delivery_time = max_delivery_time;
  490.     sd->min_retry_wait = min_retry_wait;
  491.  
  492.     /*
  493.      * Initialize the global state.
  494.      */
  495.     if ((sd->q = list_make(NULL, free)) == NULL) {
  496.     log(L_EMERG, "can't initialize queue: %m");
  497.     return (-1);
  498.     }
  499.  
  500.     /*
  501.      * Load up whatever work was left in the work queue.
  502.      */
  503.     queue_read(sd->q, sd->out_qdir);
  504.  
  505.     /*
  506.      * Setup for incoming faxes.
  507.      */
  508.     init_for_recv(sd);
  509.  
  510.     /*
  511.      * Setup for TCP connection for queue and enqueuing requests.
  512.      */
  513.     init_for_jobs(sd);
  514.  
  515.     /*
  516.      * Add the periodic queue scanner and go.
  517.      */
  518.     dispatch_register_periodic(0, 10.0, run_queue, (char *)sd);
  519.     dispatch_run();
  520.  
  521.     return (-1);
  522. }
  523.