home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / mail / delivery / deliver.tz / deliver / uucp.c < prev   
Encoding:
C/C++ Source or Header  |  1992-12-07  |  6.3 KB  |  305 lines

  1. /* $Header: uucp.c,v 2.6 90/05/03 10:35:51 chip Exp $
  2.  *
  3.  * Handle mail destined for other hosts via UUCP.
  4.  * Deliver is intended as a very low-level program, so we don't
  5.  * do anything fancy here.  We just hand the message to uux.
  6.  *
  7.  * $Log:    uucp.c,v $
  8.  * Revision 2.6  90/05/03  10:35:51  chip
  9.  * Quiet lint.
  10.  * 
  11.  * Revision 2.5  90/05/03  10:26:21  chip
  12.  * Combine destinations with a common first hop.
  13.  * 
  14.  * Revision 2.4  90/02/23  14:16:54  chip
  15.  * Support "#!" in delivery files.
  16.  * Support "user|program" and "user?error" from delivery files.
  17.  * Improve debugging and error message formatting.
  18.  * Rearrange code for clarity.
  19.  * 
  20.  * Revision 2.3  89/12/19  16:26:41  network
  21.  * Execute UUCP in real, not effective, context.
  22.  * This allows users to cancel their UUCP jobs.
  23.  * 
  24.  * Revision 2.2  89/11/01  12:31:17  network
  25.  * Use the new exists() function.
  26.  * 
  27.  * Revision 2.1  89/06/09  12:25:44  network
  28.  * Update RCS revisions.
  29.  * 
  30.  * Revision 1.5  89/06/09  12:24:02  network
  31.  * Baseline for 2.0 release.
  32.  * 
  33.  */
  34.  
  35. #include "deliver.h"
  36.  
  37. /*
  38.  * Local functions.
  39.  */
  40.  
  41. static    char    *find_uux();
  42. static  int     uucp_copy();
  43.  
  44. /*----------------------------------------------------------------------
  45.  * Send mail to UUCP addresses (if any).
  46.  * Return count of UUCP addresses for which delivery was attempted.
  47.  */
  48.  
  49. int
  50. uucp_deliver()
  51. {
  52.     DEST    *d;
  53.     char    *uav[UUX_ARGCOUNT + 8];     /* arguments for execv() */
  54.     char    **av;                /* remote addresses in uav[] */
  55.     DEST    *dv[UUX_ARGCOUNT];        /* destinations in av[] */
  56.     char    rmail[UUCP_NAMESIZE + 8];   /* "sysname!rmail" */
  57.     char    *uux;
  58.     int    uucpcount;
  59.  
  60.     if ((uux = find_uux()) == NULL)
  61.         return -1;
  62.  
  63.     av = uav;
  64.     *av++ = "uux";
  65. #ifdef UUX_OPTS
  66.     *av++ = UUX_OPTS;
  67. #endif
  68.     *av++ = "-";
  69.     *av++ = rmail;
  70.  
  71.     /*
  72.      * Look for a UUCP address that is "working".  If we find one,
  73.      * then we scan the rest of the list for other UUCP addresses
  74.      * that begin with the same first hop.  If we find any, then
  75.      * we handle them too.  Note that as we continue scanning,
  76.      * we'll find those same addresses again; that's okay, though,
  77.      * because their status fields will report that they're
  78.      * already done.  Cool, eh?
  79.      */
  80.  
  81.     uucpcount = 0;
  82.  
  83.     for (d = first_dest(); d; d = next_dest(d))
  84.     {
  85.         FILE    *uux_fp;
  86.         DEST    *ud;
  87.         DERROR    e;
  88.         char    *bang;
  89.         int    namesize, argcount, argsize, problem, a;
  90.  
  91.         if (d->d_class != CL_UUCP || d->d_state != ST_WORKING)
  92.             continue;
  93.  
  94.         ++uucpcount;
  95.  
  96.         if (printaddrs)
  97.             (void) printf("%s\n", d->d_name);
  98.  
  99.         if (dryrun)
  100.         {
  101.             d->d_state = ST_DONE;
  102.             continue;
  103.         }
  104.  
  105.         /*
  106.          * This is the first destination with the given system
  107.          * as the first hop.  Generate the rmail command.
  108.          */
  109.  
  110.         if ((bang = strchr(d->d_name, '!')) == NULL
  111.          || (namesize = bang - d->d_name) > UUCP_NAMESIZE)
  112.         {
  113.             dest_err(d, E_NSHOST);
  114.             continue;
  115.         }
  116.  
  117.         (void) strncpy(rmail, d->d_name, namesize);
  118.         (void) strcpy(rmail + namesize, "!rmail");
  119.  
  120.         /*
  121.          * Now keep looking for addresses until a limit is reached,
  122.          * either max arguments or max argument size.
  123.          * We'll find them again, but their statuses will prevent us
  124.          * from trying to mail to them twice.
  125.          */
  126.  
  127.         argcount = 0;
  128.         argsize = 0;
  129.         for (ud = d; ud; ud = next_dest(ud))
  130.         {
  131.             char *rest, *arg;
  132.  
  133.             if (ud->d_class != CL_UUCP
  134.              || ud->d_state != ST_WORKING)
  135.                 continue;
  136.  
  137.             if (strncmp(ud->d_name, d->d_name, namesize + 1) != 0)
  138.                 continue;
  139.  
  140.             /*
  141.              * We have a match!  (Or, it could be the first one.)
  142.              * Be sure we don't exceed our configured maxima,
  143.              * except for the first address, which always goes.
  144.              */
  145.  
  146.             rest = ud->d_name + namesize + 1;
  147.  
  148.             if (argcount > 0)
  149.             {
  150.                 if (argcount + 1 > UUX_ARGCOUNT
  151.                  || argsize + strlen(rest) + 2 > UUX_ARGSIZE)
  152.                     break;
  153.             }
  154.  
  155.             /*
  156.              * Generate a uux argument and save the destination.
  157.              */
  158.  
  159.             arg = zalloc((unsigned) 3 + strlen(rest));
  160.             (void) sprintf(arg, "(%s)", rest);
  161.  
  162.             av[argcount] = arg;
  163.             dv[argcount] = ud;
  164.  
  165.             /*
  166.              * Keep track of arg count and total size.
  167.              */
  168.  
  169.             ++argcount;
  170.             argsize += strlen(arg);
  171.         }
  172.  
  173.         av[argcount] = NULL;
  174.  
  175.         /*
  176.          * Do the dirty deed.
  177.          * We have to remember the error code as a variable,
  178.          * since it may apply to multiple destinations.
  179.          */
  180.  
  181.         problem = 0;
  182.         e = E_PIPE;    /* default error */
  183.  
  184.         if ((uux_fp = ct_fopenv(real_ct, uux, uav, "w")) == NULL)
  185.             problem = 1;
  186.         else
  187.         {
  188.             if (uucp_copy(uux_fp) < 0)
  189.                 problem = 1;
  190.  
  191.             if (ct_fclose(uux_fp))
  192.             {
  193.                 /* "No such host" overrides piping problems. */
  194.                 e = E_NSHOST;
  195.                 problem = 1;
  196.             }
  197.         }
  198.  
  199.         /*
  200.          * We're done.  Update each destination's status.
  201.          */
  202.  
  203.         for (a = 0; a < argcount; ++a)
  204.         {
  205.             free(av[a]);
  206.  
  207.             if (problem)
  208.                 dest_err(dv[a], e);
  209.             else
  210.                 dv[a]->d_state = ST_DONE;
  211.         }
  212.  
  213.         /* Track the correct count of UUCP addresses found. */
  214.  
  215.         uucpcount += argcount - 1;
  216.     }
  217.  
  218.     return uucpcount;
  219. }
  220.  
  221. /*----------------------------------------------------------------------
  222.  * Where is uux?
  223.  */
  224.  
  225. static char *
  226. find_uux()
  227. {
  228.     static char uux1[] = "/bin/uux";
  229.     static char uux2[] = "/usr/bin/uux";
  230.  
  231.     if (exists(uux1))
  232.         return uux1;
  233.     if (exists(uux2))
  234.         return uux2;
  235.     error("can't find uux!?\n");
  236.     return NULL;
  237. }
  238.  
  239. /*----------------------------------------------------------------------
  240.  * Write the message for UUCP transmission to the given file.
  241.  */
  242.  
  243. static int
  244. uucp_copy(ofp)
  245. FILE    *ofp;
  246. {
  247.     FILE    *ifp;
  248.     char    *p;
  249.     register int c;
  250.     int     fd;
  251.     char    buf[BUFSIZ];
  252.  
  253.     if ((fd = dup(tfd[T_HDR])) == -1)
  254.     {
  255.         syserr("can't dup header fd");
  256.         return -1;
  257.     }
  258.     (void) lseek(fd, 0L, 0);
  259.     if ((ifp = fdopen(fd, "r")) == NULL)
  260.     {
  261.         error("can't fdopen header fd");
  262.         return -1;
  263.     }
  264.  
  265.     /*
  266.      * Copy the header, but tack "remote from" onto the end of the
  267.      * From_ line.  (If it weren't for dealing with the From_ line,
  268.      * I'd skip stream I/O altogether and use read/write.  Maybe
  269.      * I should save the length of the From_ line when I copy it...)
  270.      */
  271.  
  272.     (void) fgets(buf, GETSIZE(buf), ifp);
  273.     if ((p = strchr(buf, '\n')) != NULL)
  274.         *p = 0;
  275.     (void) fprintf(ofp, "%s remote from %s\n", buf, hostname);
  276.  
  277.     while ((c = getc(ifp)) != EOF)
  278.         (void) putc(c, ofp);
  279.  
  280.     (void) fclose(ifp);
  281.  
  282.     /*
  283.      * Copy the body
  284.      */
  285.  
  286.     if ((fd = dup(tfd[T_BODY])) == -1)
  287.     {
  288.         syserr("can't dup body fd");
  289.         return -1;
  290.     }
  291.     (void) lseek(fd, 0L, 0);
  292.     if ((ifp = fdopen(fd, "r")) == NULL)
  293.     {
  294.         error("can't fdopen body fd");
  295.         (void) close(fd);
  296.         return -1;
  297.     }
  298.  
  299.     while ((c = getc(ifp)) != EOF)
  300.         (void) putc(c, ofp);
  301.  
  302.     (void) fclose(ifp);
  303.     return 0;
  304. }
  305.