home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8708 / 21 / pcmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-13  |  14.1 KB  |  626 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. #ifdef MSDOS
  217.      mcurdir = getcwd( s_mcurdir, sizeof(s_mcurdir) );
  218. #else
  219.     mcurdir = getcwd( s_mcurdir, 0 );
  220. #endif
  221.     chdir( spooldir );
  222.  
  223.     /* get sequence number */
  224.     mkfilename( tfilename, confdir, SFILENAME );
  225.  
  226.      if ( debuglevel > 4 )
  227.         fprintf( stderr, "pcmail: opening %s\n", tfilename ); /* */
  228.  
  229.     tempfile = FOPEN( tfilename, "r", 't' );
  230.     if (tempfile != (FILE *)NULL) {
  231.         fscanf( tempfile, "%ld", &sequence );
  232.         fclose( tempfile );
  233.     }
  234.      else {
  235.          fprintf( stderr, "pcmail: can't find %s file, creating\n",
  236.                      tfilename );
  237.          sequence = 1;    /* start at 1 */
  238.      };
  239.  
  240.     /* update sequence number */
  241.     if ( debuglevel > 5 )
  242.         fprintf( stderr, "pcmail: new sequence # %ld\n", sequence );
  243.  
  244.     tempfile = FOPEN( tfilename, "w", 't' );
  245.     if (tempfile != (FILE *)NULL) {
  246.         fprintf( tempfile, "%ld\n", sequence+1 );
  247.         fclose( tempfile );
  248.     }
  249.  
  250.     /* open a temporary file */
  251.     /* sprintf( tfilename, TFILENAME, sequence ); */
  252.      sprintf( miscbuff, TFILENAME, sequence );
  253.      mkfilename( tfilename, tempdir, miscbuff );
  254.  
  255.      if ( debuglevel > 5 )
  256.          fprintf( stderr, "pcmail: opening %s\n", tfilename );
  257.  
  258.     tempfile = FOPEN( tfilename, "w", 'b' );
  259.      if (tempfile == (FILE *)NULL)  {
  260.         fprintf( stderr, "pcmail: can't open %s\n", tfilename );
  261.         exit(1);
  262.     }
  263.  
  264.     /* copy stdin to tempfile, counting content lines and bytes */
  265.     header = 1;
  266.     while (fgets( buf, 512, stdin ) != (char *)NULL) {
  267.         if (header != 0) {
  268.             if (strlen( buf ) == 1) {
  269.                 header = 0;
  270.                 fprintf( tempfile, "\n" );
  271.                 continue;
  272.             }
  273.             else if (strchr( buf, ':' ) == NULL) {
  274.                 header = 0;
  275.                 fprintf( tempfile, "\n" );
  276.             }
  277.         }
  278.         if (header == 0) {
  279.             lines++;
  280.             bytes += strlen( buf );
  281.         }
  282.         fputs( buf, tempfile );
  283.     }
  284. #ifndef RMAIL
  285.     /* copy stdin to tempfile, counting content lines and bytes */
  286.     /* get signature */
  287.     mkfilename( mfilename, home, SIGFILE );
  288.  
  289.     if (debuglevel > 4)
  290.         fprintf( stderr, "pcmail: opening sigfile %s\n", mfilename );
  291.     mailfile = FOPEN( mfilename, "r", 't' );
  292.     if (mailfile != (FILE *)NULL) {
  293.         fputs( "\n--\n", tempfile );
  294.         while (fgets( buf, 512, mailfile ) != (char *)NULL) {
  295.             lines++;
  296.             bytes += strlen( buf );
  297.             fputs( buf, tempfile );
  298.         }
  299.         fclose( mailfile );
  300.      }
  301. #endif
  302.  
  303.      fclose( tempfile );
  304.  
  305.     if ( debuglevel > 4 ) {
  306.         fprintf( stderr, "pcmail: stdin copied to tmp %ld %ld\n",
  307.                      bytes, lines );
  308.          fprintf( stderr, "pcmail: args %d\n", argc );
  309.     }
  310.  
  311.     /* loop on args, copying to appropriate postbox,
  312.        do remote only once
  313.        remote checking is done empirically, could be better
  314.     */
  315.     remotes[0] = '\0';
  316.  
  317.  
  318. #ifndef RMAIL
  319.     if ( strcmp( argv[1], "-s" ) == SAME ) {
  320.         argv++;argv++;
  321.         argc--;argc--;
  322.         if ( argc == 0 )
  323.             return( -1 );
  324.         strcpy( Subject, *argv );
  325.         }
  326. #endif
  327.     argcount = argc;
  328.     argvec = argv;
  329.  
  330.     while (--argcount > 0) {
  331.         argvec++;
  332.         if ( debuglevel > 5 )
  333.             fprintf( stderr, "pcmail: arg# %d\ %s\n",
  334.                             argcount, *argvec );
  335.  
  336.         if (
  337.             (strchr( *argvec, '!' ) != SAME) ||
  338.             (strchr( *argvec, '@' ) != SAME) ||
  339.             (strchr( *argvec, '%' ) != SAME)
  340.            ) {
  341.             if ( debuglevel > 5 )
  342.                 fprintf( stderr, "pcmail: send to remote\n" );
  343.  
  344.             s1 = strlen( remotes );
  345.             s2 = strlen( *argvec );
  346.  
  347.             /* can we cram one more address on line */
  348.             if ( s1 > 0 && (s1 + s2 + 1) > 128 ) {
  349.                 /* dump it then, to bad */
  350.                 sendone( argc, argv, remotes, TRUE );
  351.                 remotes[0] = '\0';
  352.             }
  353.  
  354.             /* add *arvgvec to list of remotes */
  355.             strcat( remotes, " " );
  356.             strcat( remotes, *argvec );
  357.  
  358.         }
  359.         else {
  360.             if ( debuglevel > 5 )
  361.                 fprintf( stderr, "pcmail: calling sendone %s\n",
  362.                             *argvec );
  363.  
  364.             sendone( argc, argv, *argvec, FALSE );
  365.         }
  366.  
  367.     }
  368.     /* dump remotes if necessary */
  369.     if ( strlen( remotes ) > 0 )
  370.         sendone( argc, argv, remotes, TRUE );
  371.  
  372. #ifndef RMAIL
  373.  
  374.     mkfilename( mailsent, home, COPYFILE );
  375.     if ( debuglevel > 4 )
  376.        fprintf( stderr, "pcmail: copfile = %s\n", mailsent );
  377.     sendone( argc, argv, mailsent, FALSE );
  378.  
  379. #endif
  380.  
  381.     unlink( tfilename );
  382.     chdir( mcurdir );
  383.     exit(0);
  384. }
  385.  
  386.  
  387. char fpat1[] = "%c.%.7s%04ld";
  388. char fpat2[] = "S %s %s %s - %s 0666 %s";
  389.  
  390.  
  391. /* sendone copies file plus headers to appropriate postbox
  392.    NB. we do headers here to allow flexibility later, for example
  393.    in being able to do bcc, per host service processing etc.
  394. */
  395. sendone( argc, argv, address, remote )
  396. char **argv;
  397. int argc;
  398. char *address;
  399. {
  400.     register char     *cp;
  401.     char    icfilename[32];        /* local C. copy file */
  402.     char    ixfilename[32];        /* local X. xqt file */
  403.     char    idfilename[32];        /* local D. data file */
  404.     char    rxfilename[32];        /* remote X. xqt file */
  405.     char    rdfilename[32];        /* remote D. data file */
  406.      char    tmfilename[32];        /* temporary storage */
  407. #if MSDOS
  408.      char    cixfilename[32];        /* canonical ixfilename */
  409.      char    cidfilename[32];        /* canonical idfilename */
  410. #endif
  411.      if ( remote ) {
  412.          /* sprintf all required file names */
  413.         sprintf( tmfilename, fpat1, 'C', mailserv, sequence );
  414.         importpath( icfilename, tmfilename );
  415. #ifdef MSDOS
  416.          sprintf( cidfilename, fpat1, 'D', mailserv, sequence );
  417.         importpath( idfilename, cidfilename );
  418.         sprintf( cixfilename, fpat1, 'D', nodename, sequence );
  419.          importpath( ixfilename, cixfilename );
  420. #else
  421.         sprintf( tmfilename, fpat1, 'D', mailserv, sequence );
  422.         importpath( idfilename, tmfilename );
  423.         sprintf( tmfilename, fpat1, 'D', nodename, sequence );
  424.         importpath( ixfilename, tmfilename );
  425. #endif
  426.         sprintf( rdfilename, fpat1, 'D', nodename, sequence );
  427.         sprintf( rxfilename, fpat1, 'X', nodename, sequence );
  428.      }
  429.      else {
  430.         /* postbox file name */
  431.          if ( index( address, SEPCHAR ) == (char *)NULL )
  432.             mkfilename( idfilename, maildir, address );
  433.         else
  434.             strcpy( idfilename, address );
  435.     }
  436.  
  437.     if ( debuglevel > 5 )
  438.          fprintf( stderr, "pcmail: sendone: %s\n", idfilename );
  439.  
  440.      if ( remote == FALSE ) {
  441.         if ( debuglevel > 5 )
  442.            fprintf( stderr, "pcmail: sendone: check for remote\n" );
  443.         /* check for forwarding */
  444.         if ( (mailfile = FOPEN( idfilename, "r", 'b' )) != (FILE *)NULL ) {
  445.             cp = fgets( buf, BUFSIZ, mailfile );
  446.             fclose( mailfile );
  447.             if (cp != (char *)NULL)
  448.                 if (strncmp( buf, FORWARD, 10 ) == 0) {
  449.                     strcpy( buf, buf+11 );
  450.                     return( sendone( argc, argv, buf, FALSE ) );
  451.                 }
  452.         }
  453.     }
  454.  
  455.     /* open mailfile */
  456.     if ( (mailfile = FOPEN( idfilename, "a", 'b' )) == (FILE *)NULL ) {
  457.         fprintf( stdout, "pcmail: cannot append to %s\n", idfilename );
  458.         return( 0 );
  459.     }
  460.  
  461.     if ( debuglevel > 5 )
  462.         fprintf( stderr, "pcmail: append to mailfile\n" );
  463.  
  464.     tloc = time( (long *)NULL );
  465.     thetime = ctime(&tloc);
  466.      (void)strcpy(chartime, thetime);    /* make our own copy */
  467.      thetime = chartime;    /* and work with our own copy */
  468.     thetime[strlen(thetime)-1] = '\0';
  469.  
  470. #ifdef RMAIL
  471.     fprintf( mailfile, "From uucp %s", thetime );
  472.     fputc( '\012', mailfile );
  473.     fprintf( mailfile, "Received: by %s (pcmail) %s", domain, thetime );
  474.     fputc( '\012', mailfile );
  475. #else /* RMAIL */
  476.     fprintf( mailfile, "From %s %s", mailbox, thetime );
  477.     if ( remote )
  478.         fprintf( mailfile, " remote from %s", nodename );
  479.     fputc( '\012', mailfile );
  480.     fprintf( mailfile, "Received: by %s (pcmail) %s", domain, thetime );
  481.     fputc( '\012', mailfile );
  482.     fprintf( mailfile, "Date: %s", thetime );
  483.     fputc( '\012', mailfile );
  484.     /* add Date:, From: and Message-ID: headers */
  485.     fprintf( mailfile, "From: %s <%s@%s>", name, mailbox, domain );
  486.     fputc( '\012', mailfile );
  487.     fprintf( mailfile, "Message-ID: <%ld@%s>", sequence, domain );
  488.     fputc( '\012', mailfile );
  489.     /* add To: headers */
  490.     while (--argc > 0) {
  491.         fprintf( mailfile, "To: %s", *++argv );
  492.         fputc( '\012', mailfile );
  493.     }
  494.     if ( strlen( Subject ) > 0 ) {
  495.         fprintf( mailfile, "Subject: %s", Subject );
  496.         fputc( '\012', mailfile );
  497.     }
  498. #ifdef PCMAIL
  499.     /* add Message-Lines: and Content-Length: headers */
  500.     fprintf( mailfile, "X-Message-Lines: %ld", lines );
  501.     fputc( '\012', mailfile );
  502.     fprintf( mailfile, "Content-Length: %ld", bytes );
  503.     fputc( '\012', mailfile );
  504. #endif /* PCMAIL */
  505. #endif /* RMAIL */
  506.  
  507.     /* copy tempfile to postbox file */
  508.     if (debuglevel > 4)
  509.        fprintf( stderr, "pcmail: copy tempfile %s to %s\n",
  510.                         tfilename, idfilename );
  511.     tempfile = FOPEN( tfilename, "r", 'b' );
  512.     if ( tempfile == (FILE *)NULL) {
  513.         fprintf( stdout, "pcmail: can't re-open %s\n", tfilename );
  514.         return( 0 );
  515.     }
  516.     while (fgets( buf, 512, tempfile ) != (char *)NULL) {
  517.         if ( strncmp( buf, "From ", 5 ) == 0 )
  518.             fputc( '>', mailfile );
  519.         cp = &buf[ strlen(buf)-1 ];
  520.         if ( *cp == '\n' )
  521.             *cp = '\0';
  522.         fputs( buf, mailfile );
  523.         fputc( '\012', mailfile );
  524.      }
  525.  
  526.     /* close files */
  527.     fclose( mailfile );
  528.     fclose( tempfile );
  529.  
  530.     /* all done unless going to remote via uucp */
  531.     /* must create the job control files */
  532.     if ( remote == TRUE ) {
  533.  
  534.         /* create remote X xqt file */
  535.         mailfile = FOPEN( ixfilename, "w", 'b' );
  536.         if     (mailfile == (FILE *)NULL) {
  537.             fprintf( stdout, "pcmail: cannot append to %s\n", ixfilename );
  538.             return( 0 );
  539.         }
  540.         fprintf( mailfile, "U %s %s", uucp, nodename );
  541.         fputc( '\012', mailfile );
  542.         fprintf( mailfile, "F %s", rdfilename );
  543.         fputc( '\012', mailfile );
  544.         fprintf( mailfile, "I %s", rdfilename );
  545.         fputc( '\012', mailfile );
  546.         fprintf( mailfile, "C rmail %s", address );
  547.         fputc( '\012', mailfile );
  548.         fclose( mailfile );
  549.  
  550.         /* create local C copy file */
  551.         mailfile = FOPEN( icfilename, "w", 't' );
  552.         if     (mailfile == (FILE *)NULL) {
  553.             fprintf( stdout, "pcmail: cannot append to %s\n", icfilename );
  554.             return( 0 );
  555.         }
  556.  
  557. #if MSDOS
  558.          fprintf( mailfile, fpat2, cidfilename, rdfilename,
  559.                      uucp, cidfilename, uucp );
  560.          fputc( '\012', mailfile );
  561.          fprintf( mailfile, fpat2, cixfilename, rxfilename,
  562.                      uucp, cixfilename, uucp );
  563.          fputc( '\012', mailfile );
  564. #else
  565.         fprintf( mailfile, fpat2, idfilename, rdfilename,
  566.                     uucp, idfilename, uucp );
  567.         fputc( '\012', mailfile );
  568.         fprintf( mailfile, fpat2, ixfilename, rxfilename,
  569.                     uucp, ixfilename, uucp );
  570.         fputc( '\012', mailfile );
  571. #endif
  572.         fclose( mailfile );
  573.  
  574.     } /* if ( remote == TRUE ) */
  575.  
  576.     return( 1 );
  577. }
  578.  
  579. #ifndef AMIGA
  580. #ifdef RMAIL
  581. rnews(argc, argv)
  582. int argc;
  583. char *argv[];
  584. {
  585.     struct tm    *thetm;
  586.     char    filename[132];
  587.     char    format[128];
  588.     FILE     *f;
  589.     char    buf[BUFSIZ];
  590.  
  591.     static int count = 0;
  592.  
  593.     tloc = time( (long *)NULL );
  594.     thetime = ctime(&tloc);
  595.     tloc = time( (long *)NULL );
  596.  
  597.     thetm = localtime( &tloc );
  598.  
  599.     /* mkfilename( format, spooldir, NEWSDIR );    */
  600.     sprintf( filename, NEWSDIR,
  601.         thetm->tm_year % 100, thetm->tm_mon,
  602.         thetm->tm_mday, thetm->tm_hour,
  603.         thetm->tm_min,  thetm->tm_sec,  count
  604.         );
  605.  
  606.     count++;
  607.  
  608.     if ( debuglevel > 5 )
  609.         fprintf( stderr, "rnews: %s\n", filename );
  610.  
  611.     if ( (f = FOPEN( filename, "w", 't' )) == (FILE *)NULL ) {
  612.         fprintf( stderr, "rnews: can't open %s %d\n", filename, errno );
  613.         return( -1 );
  614.     }
  615.  
  616.     while ( fgets( buf, BUFSIZ, stdin ) != (char *)NULL )
  617.         fputs( buf, f );
  618.  
  619.     fclose( f );
  620. }
  621.  
  622. #endif /* RMAIL */
  623. #endif /* AMIGA */
  624.  
  625.  
  626.