home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d109 / uupc.lha / UUpc / Source / pcmail.c < prev    next >
C/C++ Source or Header  |  1987-10-28  |  14KB  |  601 lines

  1. /*         pcmail.c
  2.  
  3.  
  4.  
  5.         copyright (C) 1987 Stuart Lynne
  6.  
  7.         Copying and use of this program are controlled by the terms of the
  8.         Free Software Foundations GNU Emacs General Public License.
  9.  
  10.  
  11.         version        0.1        March 31/1987
  12.  
  13.     
  14. pcmail
  15.  
  16.         pcmail address1 address2 ... < the.message
  17.  
  18. description
  19.  
  20.     An 822 compatible (hopefully) mail delivery system for pc's.
  21.  
  22.     Designed for delivering mail on a pc based system. It will put
  23.     local mail (ie, not @ or ! in address) into files in the default
  24.     mail directory.
  25.  
  26.     If remote it will put into an outgoing mailbag in the default mail
  27.     directory. Performs a simple bundling of mail messages into one 
  28.     file with arguments prepended as To: arg header lines. And adds a 
  29.     Message-Lines: header which gives the number of lines in the
  30.     content part of the message (after the first blank line).
  31.  
  32.         pcmail john jack jill@xyz.uucp < afile
  33.  
  34.         To: john
  35.         To: jack
  36.         To: jill@xyz.uucp
  37.         X-Message-Lines: ?????
  38.         Content-Length: ?????
  39.  
  40.         ...
  41.         ...
  42.         ...
  43.  
  44.     Content-Length: is used without X- prepended to be compatible with AT&T
  45.     Mail bundles. This is not 822 compatible per se, but is allowed.
  46.  
  47.     It also adds the from From and Date lines. Subject: lines may be inserted
  48.     by placing them at the beginning of the message.
  49.  
  50.     A Unix version should lock the /usr/mail/mailbag file.
  51.  
  52.     Another program called rpcmail will unbundle the files created by 
  53.     pcmail and deliver each message to the local rmail. So conceptually
  54.  
  55.         (pcmail ..... < ...; pcmail .... < ...) | sz -> rz | rpcmail
  56.  
  57.     would deliver remote messages intact.
  58.  
  59. environment variables
  60.  
  61.     The following evironment variables are used:
  62.  
  63.         MAILBOX        current user's mailbox,     "stuart"
  64.         NAME        current user's name,         "Stuart Lynne"
  65.         DOMAIN        domain of this machine,     "slynne.mac.van-bc.can"
  66.         MAILDIR        where is mail kept,            "mpw:mail"
  67.  
  68. compiling
  69.  
  70.     Compiled by itself it will operate as a standalone program. If the 
  71.     compiler option:
  72.  
  73.         -DNOMAIN
  74.     
  75.     is used, it will compile as a routine:
  76.  
  77.         pcmail (argc, argv)
  78.         char **argv;
  79.         int argc;
  80.  
  81.     and can be used internally in other programs.
  82.  
  83.  
  84. Customization
  85.  
  86.     PCMAIL        mailbag for remote mail
  87.     FAKEUUX        emulate uux, make appropriate files in SPOOLDIR
  88.  
  89.     RMAIL        rmail
  90.  
  91.     DEBUG1        first level Debug trace
  92.  
  93.  
  94. */
  95.  
  96. /*
  97. #ifdef NOMAIN
  98. #include "dcp.h"
  99. #else
  100. */
  101. #include <stdio.h>
  102. #include "host.h"
  103. /*
  104. #endif
  105. */
  106.  
  107. FILE *FOPEN();
  108.  
  109. #define FORWARD        "Forward to"
  110.  
  111.  
  112. #define    SBUFSIZ        124
  113.  
  114. FILE   *mailfile;
  115. FILE   *tempfile;
  116.  
  117. char    buf[BUFSIZ];
  118. char    miscbuff[100];
  119. long int lines = 0;
  120. long int bytes = 0;
  121. long int sequence = 0;
  122.  
  123. long tloc;
  124. char chartime[26];    /* current time in characters */
  125. char *thetime;
  126.  
  127. char    tfilename[100];
  128. char    mfilename[100];
  129. char    mailsent[100];
  130.  
  131.  
  132. int local = TRUE;
  133.  
  134. char     remotes[BUFSIZ];
  135.  
  136.  
  137. char uucp[] = "uucp";
  138.  
  139. char *fgets();
  140. int fputs();
  141.  
  142. #ifdef NOMAIN
  143.  
  144. #ifdef RMAIL
  145. #define main    rmail
  146. #else
  147. #define    main    lmail
  148. #endif
  149.  
  150. #define exit    return
  151.  
  152. extern int debuglevel;
  153.  
  154. #else
  155. int debuglevel;
  156. #endif
  157.  
  158. #ifndef RMAIL
  159. char    Subject[132] = "";
  160. #endif
  161.  
  162. char *mcurdir;
  163. char s_mcurdir[128];    /* current directory path (save malloc call) */
  164. char * getcwd();
  165. int chdir();
  166.  
  167.  
  168.  
  169. main(argc, argv)
  170. char *argv[];
  171. {
  172.     long int position;
  173.     register int header = 1;
  174.     register int amount;
  175.  
  176.     register int argcount;
  177.     register char **argvec;
  178.     int remote;
  179.     int s1, s2;
  180.  
  181.  
  182.     
  183.  
  184. #ifndef NOMAIN
  185.     /* get environment var's */
  186.     HOSTINIT;
  187.     loadenv();
  188.  
  189.      if (argc <= 1) {
  190.         fprintf( stderr, "pcmail usage: pcmail addresses < message\n" );
  191.         exit(1);
  192.     }
  193.     debuglevel = 1;
  194.     
  195. #endif
  196. #ifdef RMAIL
  197.     local = FALSE;
  198. #else
  199.     local = TRUE;
  200. #endif
  201.  
  202.     if ( debuglevel > 5 ) {
  203.         fprintf( stderr, "pcmail: argc %d ", argc );
  204.         argcount = argc;
  205.         argvec = argv;
  206.         while (argcount--) {
  207.             fprintf( stderr, " \"%s\"", *argvec++ );
  208.             }
  209.         fprintf( stderr, "\n" );
  210.  
  211.         tloc = time( (long *)NULL );
  212.         thetime = ctime(&tloc);
  213.         fprintf( stderr, "thetime: %s\n",thetime );
  214.     }
  215.     
  216.  
  217.     mcurdir = getcwd( s_mcurdir, 0 );
  218.     chdir( spooldir );
  219.  
  220.     /* get sequence number */
  221.     mkfilename( tfilename, confdir, SFILENAME );
  222.     
  223.      if ( debuglevel > 4 )
  224.         fprintf( stderr, "pcmail: opening %s\n", tfilename ); /* */
  225.  
  226.     tempfile = FOPEN( tfilename, "r", 't' );
  227.     if (tempfile != (FILE *)NULL) {
  228.         fscanf( tempfile, "%ld", &sequence );
  229.         fclose( tempfile );
  230.     }
  231.     else 
  232.         fprintf( stderr, "pcmail: can't find %s file, creating\n",
  233.                     tfilename );
  234.  
  235.     /* update sequence number */
  236.     if ( debuglevel > 5 ) 
  237.         fprintf( stderr, "pcmail: new sequence # %ld\n", sequence ); 
  238.     
  239.     tempfile = FOPEN( tfilename, "w", 't' );
  240.     if (tempfile != (FILE *)NULL) {
  241.         fprintf( tempfile, "%ld\n", sequence+1 );
  242.         fclose( tempfile );
  243.     }
  244.  
  245.     /* open a temporary file */
  246.     /* sprintf( tfilename, TFILENAME, sequence ); */
  247.      sprintf( miscbuff, TFILENAME, sequence );
  248.      mkfilename( tfilename, tempdir, miscbuff );
  249.     
  250.      if ( debuglevel > 5 ) 
  251.          fprintf( stderr, "pcmail: opening %s\n", tfilename );
  252.  
  253.     tempfile = FOPEN( tfilename, "w", 'b' );
  254.      if (tempfile == (FILE *)NULL)  {
  255.         fprintf( stderr, "pcmail: can't open %s\n", tfilename );
  256.         exit(1);
  257.     }
  258.     
  259.     /* copy stdin to tempfile, counting content lines and bytes */
  260.     header = 1;
  261.     while (fgets( buf, 512, stdin ) != (char *)NULL) {
  262.         if (header != 0) {
  263.             if (strlen( buf ) == 1) {
  264.                 header = 0;
  265.                 fprintf( tempfile, "\n" );
  266.                 continue;
  267.             }
  268.             else if (strchr( buf, ':' ) == NULL) {
  269.                 header = 0;
  270.                 fprintf( tempfile, "\n" );
  271.             }
  272.         }
  273.         if (header == 0) {
  274.             lines++;
  275.             bytes += strlen( buf );
  276.         }
  277.         fputs( buf, tempfile );    
  278.     }
  279. #ifndef RMAIL
  280.     /* copy stdin to tempfile, counting content lines and bytes */
  281.     /* get sequence number */
  282.     mkfilename( mfilename, home, SIGFILE );
  283.     
  284.     if (debuglevel > 4)
  285.         fprintf( stderr, "pcmail: opening sigfile %s\n", mfilename );
  286.     mailfile = FOPEN( mfilename, "r", 't' );
  287.     if (mailfile != (FILE *)NULL) {
  288.         fputs( "\n--\n", tempfile );
  289.         while (fgets( buf, 512, mailfile ) != (char *)NULL) {
  290.             lines++;
  291.             bytes += strlen( buf );
  292.             fputs( buf, tempfile );    
  293.         }
  294.         fclose( mailfile );
  295.      }
  296. #endif
  297.  
  298.      fclose( tempfile );
  299.      
  300.     if ( debuglevel > 4 ) {
  301.         fprintf( stderr, "pcmail: stdin copied to tmp %ld %ld\n",
  302.                      bytes, lines ); 
  303.          fprintf( stderr, "pcmail: args %d\n", argc );
  304.     }
  305.     
  306.     /* loop on args, copying to appropriate postbox, 
  307.        do remote only once 
  308.        remote checking is done empirically, could be better
  309.     */
  310.     remotes[0] = '\0';
  311.     
  312.  
  313. #ifndef RMAIL
  314.     if ( strcmp( argv[1], "-s" ) == SAME ) {
  315.         argv++;argv++;
  316.         argc--;argc--;
  317.         if ( argc == 0 )
  318.             return( -1 );
  319.         strcpy( Subject, *argv );
  320.         }
  321. #endif
  322.     argcount = argc;
  323.     argvec = argv;
  324.         
  325.     while (--argcount > 0) {
  326.         argvec++;
  327.         if ( debuglevel > 5 ) 
  328.             fprintf( stderr, "pcmail: arg# %d\ %s\n", 
  329.                             argcount, *argvec ); 
  330.  
  331.         if (
  332.             (strchr( *argvec, '!' ) != SAME) ||
  333.             (strchr( *argvec, '@' ) != SAME) ||
  334.             (strchr( *argvec, '%' ) != SAME)
  335.            ) {
  336.             if ( debuglevel > 5 ) 
  337.                 fprintf( stderr, "pcmail: send to remote\n" ); 
  338.                 
  339.             s1 = strlen( remotes );
  340.             s2 = strlen( *argvec );
  341.  
  342.             /* can we cram one more address on line */
  343.             if ( s1 > 0 && (s1 + s2 + 1) > 128 ) {
  344.                 /* dump it then, to bad */
  345.                 sendone( argc, argv, remotes, TRUE );
  346.                 remotes[0] = '\0';
  347.             }
  348.  
  349.             /* add *arvgvec to list of remotes */
  350.             strcat( remotes, " " );
  351.             strcat( remotes, *argvec );
  352.  
  353.         }
  354.         else {
  355.             if ( debuglevel > 5 ) 
  356.                 fprintf( stderr, "pcmail: calling sendone %s\n",
  357.                             *argvec ); 
  358.                             
  359.             sendone( argc, argv, *argvec, FALSE );
  360.         }
  361.         
  362.     }
  363.     /* dump remotes if necessary */
  364.     if ( strlen( remotes ) > 0 ) 
  365.         sendone( argc, argv, remotes, TRUE );
  366.  
  367. #ifndef RMAIL
  368.  
  369.     mkfilename( mailsent, home, COPYFILE );
  370.     if ( debuglevel > 4 )
  371.        fprintf( stderr, "pcmail: copfile = %s\n", mailsent );
  372.     sendone( argc, argv, mailsent, FALSE );
  373.  
  374. #endif
  375.  
  376.     unlink( tfilename ); 
  377.     chdir( mcurdir );
  378.     exit(0);
  379. }
  380.  
  381.  
  382. char fpat1[] = "%c.%.7s%04ld";
  383. char fpat2[] = "S %s %s %s - %s 0666 %s";
  384.  
  385.  
  386. /* sendone copies file plus headers to appropriate postbox
  387.    NB. we do headers here to allow flexibility later, for example
  388.    in being able to do bcc, per host service processing etc.
  389. */
  390. sendone( argc, argv, address, remote )
  391. char **argv;
  392. int argc;
  393. char *address;
  394. {
  395.     register char     *cp;
  396.     char    icfilename[32];        /* local C. copy file */
  397.     char    ixfilename[32];        /* local X. xqt file */
  398.     char    idfilename[32];        /* local D. data file */
  399.     char    rxfilename[32];        /* remote X. xqt file */
  400.     char    rdfilename[32];        /* remote D. data file */
  401.      char    tmfilename[32];        /* temporary storage */
  402.  
  403.      if ( remote ) {
  404.          /* sprintf all required file names */
  405.         sprintf( tmfilename, fpat1, 'C', mailserv, sequence );
  406.         importpath( icfilename, tmfilename );
  407.         sprintf( tmfilename, fpat1, 'D', mailserv, sequence );
  408.         importpath( idfilename, tmfilename );
  409.         sprintf( tmfilename, fpat1, 'D', nodename, sequence );
  410.         importpath( ixfilename, tmfilename );
  411.         sprintf( rdfilename, fpat1, 'D', nodename, sequence );
  412.         sprintf( rxfilename, fpat1, 'X', nodename, sequence );
  413.      }
  414.      else {
  415.         /* postbox file name */
  416.          if ( index( address, SEPCHAR ) == (char *)NULL )
  417.             mkfilename( idfilename, maildir, address );
  418.         else
  419.             strcpy( idfilename, address );
  420.     }
  421.  
  422.     if ( debuglevel > 5 ) 
  423.          fprintf( stderr, "pcmail: sendone: %s\n", idfilename );
  424.  
  425.      if ( remote == FALSE ) {
  426.         if ( debuglevel > 5 ) 
  427.            fprintf( stderr, "pcmail: sendone: check for remote\n" );
  428.         /* check for forwarding */
  429.         if ( (mailfile = FOPEN( idfilename, "r", 'b' )) != (FILE *)NULL ) {
  430.             cp = fgets( buf, BUFSIZ, mailfile );
  431.             fclose( mailfile );
  432.             if (cp != (char *)NULL)
  433.                 if (strncmp( buf, FORWARD, 10 ) == 0) {
  434.                     strcpy( buf, buf+11 );
  435.                     return( sendone( argc, argv, buf, FALSE ) );
  436.                 }
  437.         }
  438.     }
  439.      
  440.     /* open mailfile */
  441.     if ( (mailfile = FOPEN( idfilename, "a", 'b' )) == (FILE *)NULL ) {
  442.         fprintf( stdout, "pcmail: cannot append to %s\n", idfilename );
  443.         return( 0 );
  444.     }
  445.  
  446.     if ( debuglevel > 5 ) 
  447.         fprintf( stderr, "pcmail: append to mailfile\n" );
  448.  
  449.     tloc = time( (long *)NULL );
  450.     thetime = ctime(&tloc);
  451.      (void)strcpy(chartime, thetime);    /* make our own copy */
  452.      thetime = chartime;    /* and work with our own copy */
  453.     thetime[strlen(thetime)-1] = '\0';
  454.  
  455. #ifdef RMAIL
  456.     fprintf( mailfile, "From uucp %s", thetime );
  457.     fputc( '\012', mailfile );
  458.     fprintf( mailfile, "Received: by %s (pcmail) %s", domain, thetime );
  459.     fputc( '\012', mailfile );
  460. #else RMAIL
  461.     fprintf( mailfile, "From %s %s", mailbox, thetime );
  462.     if ( remote )
  463.         fprintf( mailfile, " remote from %s", nodename );
  464.     fputc( '\012', mailfile );
  465.     fprintf( mailfile, "Received: by %s (pcmail) %s", domain, thetime );
  466.     fputc( '\012', mailfile );
  467.     fprintf( mailfile, "Date: %s", thetime );
  468.     fputc( '\012', mailfile );
  469.     /* add Date:, From: and Message-ID: headers */
  470.     fprintf( mailfile, "From: %s <%s@%s>", name, mailbox, domain );
  471.     fputc( '\012', mailfile );
  472.     fprintf( mailfile, "Message-ID: <%ld@%s>", sequence, domain );
  473.     fputc( '\012', mailfile );
  474.     /* add To: headers */
  475.     while (--argc > 0) {
  476.         fprintf( mailfile, "To: %s", *++argv );
  477.         fputc( '\012', mailfile );
  478.     }
  479.     if ( strlen( Subject ) > 0 ) {
  480.         fprintf( mailfile, "Subject: %s", Subject );
  481.         fputc( '\012', mailfile );
  482.     }
  483. #ifdef PCMAIL 
  484.     /* add Message-Lines: and Content-Length: headers */
  485.     fprintf( mailfile, "X-Message-Lines: %ld", lines ); 
  486.     fputc( '\012', mailfile );
  487.     fprintf( mailfile, "Content-Length: %ld", bytes ); 
  488.     fputc( '\012', mailfile );
  489. #endif PCMAIL
  490. #endif RMAIL
  491.  
  492.     /* copy tempfile to postbox file */
  493.     if (debuglevel > 4)
  494.        fprintf( stderr, "pcmail: copy tempfile %s to %s\n",
  495.                         tfilename, idfilename );
  496.     tempfile = FOPEN( tfilename, "r", 'b' );
  497.     if ( tempfile == (FILE *)NULL) {
  498.         fprintf( stdout, "pcmail: can't re-open %s\n", tfilename );
  499.         return( 0 );
  500.     }
  501.     while (fgets( buf, 512, tempfile ) != (char *)NULL) {
  502.         if ( strncmp( buf, "From ", 5 ) == 0 )
  503.             fputc( '>', mailfile );
  504.         cp = &buf[ strlen(buf)-1 ];
  505.         if ( *cp == '\n' )
  506.             *cp = '\0';
  507.         fputs( buf, mailfile );
  508.         fputc( '\012', mailfile );
  509.      }
  510.      
  511.     /* close files */
  512.     fclose( mailfile );    
  513.     fclose( tempfile );
  514.  
  515.     /* all done unless going to remote via uucp */
  516.     /* must create the job control files */
  517.     if ( remote == TRUE ) {
  518.  
  519.         /* create remote X xqt file */
  520.         mailfile = FOPEN( ixfilename, "w", 'b' );
  521.         if     (mailfile == (FILE *)NULL) {
  522.             fprintf( stdout, "pcmail: cannot append to %s\n", ixfilename );
  523.             return( 0 );
  524.         }
  525.         fprintf( mailfile, "U %s %s", uucp, nodename );
  526.         fputc( '\012', mailfile );
  527.         fprintf( mailfile, "F %s", rdfilename );
  528.         fputc( '\012', mailfile );
  529.         fprintf( mailfile, "I %s", rdfilename );
  530.         fputc( '\012', mailfile );
  531.         fprintf( mailfile, "C rmail %s", address );
  532.         fputc( '\012', mailfile );
  533.         fclose( mailfile );
  534.  
  535.         /* create local C copy file */
  536.         mailfile = FOPEN( icfilename, "w", 't' );
  537.         if     (mailfile == (FILE *)NULL) {
  538.             fprintf( stdout, "pcmail: cannot append to %s\n", icfilename );
  539.             return( 0 );
  540.         }
  541.         
  542.         fprintf( mailfile, fpat2, idfilename, rdfilename,
  543.                     uucp, idfilename, uucp );
  544.         fputc( '\012', mailfile );
  545.         fprintf( mailfile, fpat2, ixfilename, rxfilename,
  546.                     uucp, ixfilename, uucp );
  547.         fputc( '\012', mailfile );
  548.         fclose( mailfile );
  549.         
  550.     } /* if ( remote == TRUE ) */
  551.     
  552.     return( 1 );
  553. }
  554.  
  555. #ifndef AMIGA
  556. #ifdef RMAIL
  557. rnews(argc, argv)
  558. int argc;
  559. char *argv[];
  560. {
  561.     struct tm    *thetm;
  562.     char    filename[132];
  563.     char    format[128];
  564.     FILE     *f;
  565.     char    buf[BUFSIZ];
  566.     
  567.     static int count = 0;
  568.     
  569.     tloc = time( (long *)NULL );
  570.     thetime = ctime(&tloc);
  571.     tloc = time( (long *)NULL );
  572.  
  573.     thetm = localtime( &tloc );
  574.  
  575.     /* mkfilename( format, spooldir, NEWSDIR );    */
  576.     sprintf( filename, NEWSDIR,
  577.         thetm->tm_year % 100, thetm->tm_mon,
  578.         thetm->tm_mday, thetm->tm_hour,
  579.         thetm->tm_min,  thetm->tm_sec,  count
  580.         );
  581.  
  582.     count++;
  583.     
  584.     if ( debuglevel > 5 )
  585.         fprintf( stderr, "rnews: %s\n", filename );
  586.     
  587.     if ( (f = FOPEN( filename, "w", 't' )) == (FILE *)NULL ) {
  588.         fprintf( stderr, "rnews: can't open %s %d\n", filename, errno );
  589.         return( -1 );
  590.     }
  591.  
  592.     while ( fgets( buf, BUFSIZ, stdin ) != (char *)NULL ) 
  593.         fputs( buf, f );
  594.  
  595.     fclose( f );
  596. }
  597.  
  598. #endif RMAIL
  599. #endif AMIGA
  600.  
  601.