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 / receive.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-31  |  7.1 KB  |  334 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 <termios.h>
  23. #include <fcntl.h>
  24. #include <malloc.h>
  25. #include <sys/param.h>
  26. #include <sys/wait.h>
  27.  
  28. #include "../../lib/libutil/dispatch.h"
  29. #include "../../lib/libutil/reap.h"
  30. #include "../../lib/libfax/libfax.h"
  31. #include "spooler.h"
  32. #include "seq.h"
  33. #include "receive.h"
  34.  
  35. /*
  36.  * This should also write stuff to the modem.
  37.  */
  38. int recv_disable(sd, fm)
  39.      spooler_data *sd;
  40.      int fm;
  41. {
  42.     dispatch_unregister_fd(DIO_READ, sd->fmp[fm].fd);
  43.     return (0);
  44. }
  45.  
  46. /*
  47.  * This should also write stuff to the modem.
  48.  */
  49. int recv_enable(sd, fm)
  50.      spooler_data *sd;
  51.      int fm;
  52. {
  53.     int recv_handler();
  54.  
  55.     /*
  56.      * Make sure nothing is left to read.
  57.      */
  58.     tcflush(sd->fmp[fm].fd, TCIFLUSH);
  59.  
  60.     dispatch_register_fd(DIO_READ, 0, sd->fmp[fm].fd, recv_handler,
  61.              (char *)sd);
  62.     return (0);
  63. }
  64.  
  65. typedef struct _recv_exit_data {
  66.     spooler_data *sd;
  67.     int fm;
  68. } recv_exit_data;
  69.  
  70. /* ARGSUSED */
  71. static int recv_exit_handler(pid, status, data)
  72.      int pid;
  73.      int status;
  74.      char *data;
  75. {
  76.     recv_exit_data *d = (recv_exit_data *)data;
  77.  
  78.     /*
  79.      * We don't care about stopped children.
  80.      */
  81.     if (WIFSTOPPED(status))
  82.       return (0);
  83.  
  84.     /*
  85.      * Modem is no longer busy.
  86.      */
  87.     d->sd->fm_busy[d->fm] = FALSE;
  88.  
  89.     /*
  90.      * Add a read handler again.
  91.      */
  92.     recv_enable(d->sd, d->fm);
  93.  
  94.     /*
  95.      * All done with the data.
  96.      */
  97.     cfree(d);    
  98.     
  99.     log(L_INFO, "recv process has exited");
  100.     
  101.     return (0);
  102. }
  103.  
  104. static void print_fdcs_params(f, fp)
  105.      FaxModem *f;
  106.      FILE *fp;
  107. {
  108.     if (FAX_ISSET(f, FAX_F_FDCS)) {
  109.     fprintf(fp, " vr=%s br=%s wd=%s ln=%s",
  110.         t30_vr_string(&f->fdcs_params),
  111.         t30_br_string(&f->fdcs_params),
  112.         t30_wd_string(&f->fdcs_params),
  113.         t30_ln_string(&f->fdcs_params));
  114.       }
  115. }
  116.  
  117. static int receive_pages(fmp, in_dir, info_fp)
  118.      FaxModem *fmp;
  119.      char *in_dir;
  120.      FILE *info_fp;
  121. {
  122.     int page = 0;
  123.  
  124.     for (;;) {
  125.     time_t start = time(0);
  126.     char file[MAXPATHLEN];
  127.     int fd;
  128.  
  129.     /*
  130.      * Tell the modem we are ready to go.
  131.      */
  132.     switch (faxmodem_start_recv(fmp)) {
  133.       case RECV_OK:
  134.         break;
  135.       case RECV_FAILED:
  136.         fprintf(info_fp, "  page %d failed\n", page+1);
  137.         fprintf(info_fp, "\nReceived %d pages succesfully\n", page);
  138.         return (-1);
  139.       case RECV_DONE:
  140.         fprintf(info_fp, "\nReceived %d pages succesfully\n", page);
  141.         return (page);
  142.     }
  143.  
  144.     /*
  145.      * Open the file to hold the G3 data.
  146.      */
  147.     sprintf(file, "%s/%d", in_dir, page++);
  148.     if ((fd = open(file, O_WRONLY|O_CREAT, 0666)) < 0) {
  149.         log(L_ALERT, "output file open failed: %m");
  150.         fprintf(info_fp, "  page %d failed\n", page);
  151.         return (-1);
  152.     }
  153.     
  154.     /*
  155.      * Read in the page.
  156.      */
  157.     if (faxmodem_recv_page(fmp, fd) < 0) {
  158.         log(L_WARNING, "receive of page failed");
  159.         fprintf(info_fp, "  page %d failed\n", page);
  160.         close(fd);
  161.         return (-1);
  162.     }
  163.  
  164.     /*
  165.      * All done with the page.
  166.      */
  167.     log(L_INFO, "received page %d", page);
  168.     fprintf(info_fp, "  page %d ok", page);
  169.     print_fdcs_params(fmp, info_fp);
  170.     fprintf(info_fp, " time=%d\n", time(0) - start);
  171.     close(fd);
  172.     }
  173. }
  174.  
  175. /*
  176.  * This function does the bulk of the work for receiving a new
  177.  * fax.  It answers the modem, reads the fax, writes the G3 files,
  178.  * and mails notification.
  179.  */
  180. static int handle_incoming_fax(sd, fmp)
  181.      spooler_data *sd;
  182.      FaxModem *fmp;
  183. {
  184.     time_t start = time(0);
  185.     char in_dir[MAXPATHLEN];
  186.     char seq_file[MAXPATHLEN];
  187.     char info_file[MAXPATHLEN];
  188.     FILE *info_fp;
  189.     int seq;
  190.     int rc;
  191.  
  192.     log(L_INFO, "handling an incoming fax");
  193.  
  194.     if (faxmodem_answer(fmp) < 0) {
  195.     log(L_NOTICE, "can't anwser the phone");
  196.     faxmodem_hangup(fmp);
  197.     return (-1);
  198.     }
  199.  
  200.     sprintf(seq_file, "%s/%s", sd->in_qdir, SEQ_FILE);
  201.     if ((seq = seq_next(seq_file)) < 0) {
  202.     log(L_ALERT, "can't get incoming sequence number: %m");
  203.     faxmodem_hangup(fmp);
  204.     return (-1);
  205.     }
  206.  
  207.     sprintf(in_dir, "%s/%d", sd->in_qdir, seq);
  208.     if (mkdir(in_dir, 0775) < 0) {
  209.     log(L_ALERT, "can't make incoming directory: %m");
  210.     faxmodem_hangup(fmp);
  211.     return (-1);
  212.     }
  213.  
  214.     sprintf(info_file, "%s/LOG", in_dir);
  215.     if ((info_fp = fopen(info_file, "w+")) == NULL) {
  216.     log(L_ALERT, "can't make info file: %m");
  217.     faxmodem_hangup(fmp);
  218.     return (-1);
  219.     }
  220.  
  221.     /*
  222.      * Print the header for the info file.
  223.      */
  224.     fprintf(info_fp, "Reception of fax %d started at %s", seq, ctime(&start));
  225.     faxmodem_print_id_strings(fmp, info_fp);
  226.     fprintf(info_fp, "\n");
  227.  
  228.     /*
  229.      * Receive the pages.
  230.      */
  231.     rc = receive_pages(fmp, in_dir, info_fp);
  232.     fprintf(info_fp, "\nTotal connect time was %d seconds.\n", 
  233.         time(0) - start);
  234.  
  235.     /*
  236.      * All done.
  237.      */
  238.     faxmodem_hangup(fmp);
  239.     fclose(info_fp);
  240.     if (sd->in_email) {
  241.     char cmd[128];
  242.  
  243.     sprintf(cmd, "/usr/ucb/Mail -s \"incoming fax report\" %s < %s", 
  244.         sd->in_email, info_file);
  245.     system(cmd);
  246.     }
  247.     return (rc);
  248. }
  249.  
  250. /* ARGSUSED */
  251. static int recv_handler(fd, client_data, dtype, dio)
  252.      int fd;
  253.      char *client_data;
  254.      int dtype;
  255.      DIO *dio;
  256. {
  257.     spooler_data *sd = (spooler_data *)client_data;
  258.     recv_exit_data *d;
  259.     int fm;
  260.  
  261.     log(L_INFO, "the phone is (probably) ringing");
  262.  
  263.     /*
  264.      * We don't want to be bothered with any more events from
  265.      * this modem until we are done receiving the fax.
  266.      */
  267.     dispatch_unregister(dio);
  268.  
  269.     /*
  270.      * Find the modem number.
  271.      */
  272.     for (fm = 0; fm < sd->numb_fm; fm++) {
  273.     if (fd == sd->fmp[fm].fd)
  274.       break;
  275.     }
  276.     if (fm == sd->numb_fm) {
  277.     log(L_ALERT, "can't find the modem");
  278.     return (-1);
  279.     }
  280.  
  281.     d = (recv_exit_data *)calloc(1, sizeof(recv_exit_data));
  282.     d->sd = sd;
  283.     d->fm = fm;
  284.  
  285.     switch(reap_fork(recv_exit_handler, (char *)d)) {
  286.       case -1:
  287.     /* error */
  288.     cfree(d);
  289.     return (-1);
  290.       case 0:
  291.     /* child */
  292.     break;
  293.       default:
  294.     /* parent */
  295.     sd->fm_busy[fm] = TRUE;
  296.     return (0);
  297.     }
  298.  
  299.     /*
  300.      * We are now in the child.
  301.      */
  302.     handle_incoming_fax(sd, &sd->fmp[fm]);
  303.  
  304.     /*
  305.      * Resync resync the modem, just in case.
  306.      */
  307.     if (faxmodem_sync(&sd->fmp[d->fm], FAXMODEM_SYNC_TRIES) < 0)
  308.       log(L_EMERG, "can't resync to the modem");
  309.  
  310.     /*
  311.      * All done!
  312.      */
  313.     exit(0);
  314.  
  315.     /* we never get here, but this keeps lint happy */
  316.     return (0);
  317. }
  318.  
  319. /*
  320.  * Setup for incoming faxes.  Basically, we register read handlers
  321.  * for all the modem fds.  If any data arrives on the fd, we know
  322.  * we have an incoming fax, and we handle the call.
  323.  */
  324. int init_for_recv(sd)
  325.      spooler_data *sd;
  326. {
  327.     int fm;
  328.  
  329.     for (fm = 0; fm < sd->numb_fm; fm++)
  330.       recv_enable(sd, fm);
  331.  
  332.     return (0);
  333. }
  334.