/* Try it ... */
/*       pcmail.c



      copyright (C) 1987 Stuart Lynne

      Copying and use of this program are controlled by the terms of the
      Free Software Foundations GNU Emacs General Public License.


      version      0.1      March 31/1987


pcmail

      pcmail address1 address2 ... < the.message

description

   An 822 compatible (hopefully) mail delivery system for pc's.

   Designed for delivering mail on a pc based system. It will put
   local mail (ie, not @ or ! in address) into files in the default
   mail directory.

   If remote it will put into an outgoing mailbag in the default mail
   directory. Performs a simple bundling of mail messages into one
   file with arguments prepended as To: arg header lines. And adds a
   Message-Lines: header which gives the number of lines in the
   content part of the message (after the first blank line).

      pcmail john jack jill@xyz.uucp < afile

      To: john
      To: jack
      To: jill@xyz.uucp
      X-Message-Lines: ?????
      Content-Length: ?????

      ...
      ...
      ...

   Content-Length: is used without X- prepended to be compatible with AT&T
   Mail bundles. This is not 822 compatible per se, but is allowed.

   It also adds the from From and Date lines. Subject: lines may be inserted
   by placing them at the beginning of the message.

   A Unix version should lock the /usr/mail/mailbag file.

   Another program called rpcmail will unbundle the files created by
   pcmail and deliver each message to the local rmail. So conceptually

      (pcmail ..... < ...; pcmail .... < ...) | sz -> rz | rpcmail

   would deliver remote messages intact.

environment variables

   The following evironment variables are used:

      MAILBOX      current user's mailbox,    "stuart"
      NAME      current user's name,       "Stuart Lynne"
      DOMAIN      domain of this machine,    "slynne.mac.van-bc.can"
      MAILDIR      where is mail kept,         "mpw:mail"

compiling

   Compiled by itself it will operate as a standalone program. If the
   compiler option:

      -DNOMAIN

   is used, it will compile as a routine:

      pcmail (argc, argv)
      char **argv;
      int argc;

   and can be used internally in other programs.


Customization

   PCMAIL      mailbag for remote mail
   FAKEUUX      emulate uux, make appropriate files in SPOOLDIR

   RMAIL      rmail

   DEBUG1      first level Debug trace


*/

/* WARNING - the NOMAIN branch was commented out... */
#ifdef NOMAIN
#include "dcp.h"
#else

#include <stdio.h>
#include "host.h"

#endif


FILE *FOPEN();

#define FORWARD      "Forward to"


#define   SBUFSIZ      124

FILE   *mailfile;
FILE   *tempfile;

char   buf[BUFSIZ];
char   miscbuff[100];
long int lines = 0;
long int bytes = 0;
long int sequence = 0;

long tloc;
char chartime[26];   /* current time in characters */
char *thetime;

char   tfilename[100];
char   mfilename[100];
char   mailsent[100];


int local = TRUE;

char    remotes[BUFSIZ];


char uucp[] = "uucp";

char *fgets();
int fputs();

#ifdef NOMAIN

#ifdef RMAIL
#define main   rmail
#else
#define   main   lmail
#endif

#define exit   return

extern int debuglevel;

#else
int debuglevel;
#endif

#ifndef RMAIL
char   Subject[132] = "";
#endif

char *mcurdir;
char s_mcurdir[128];   /* current directory path (save malloc call) */
char * getcwd();
int chdir();



int MAIN(argc, argv)/*GTOAL*/
int argc;
char *argv[];
{
   long int position;
   register int header = 1;
   register int amount;

   register int argcount;
   register char **argvec;
   int remote;
   int s1, s2;




#ifndef NOMAIN
   /* get environment var's */
   HOSTINIT;
   loadenv();

    if (argc <= 1) {
      fprintf( stderr, "pcmail usage: pcmail addresses < message\n" );
      exit(1);
   }
   debuglevel = 6;/* WAS 1 - GTOAL */

#endif
#ifdef RMAIL
   local = FALSE;
#else
   local = TRUE;
#endif

   if ( debuglevel > 5 ) {
      fprintf( stderr, "pcmail: argc %d ", argc );
      argcount = argc;
      argvec = argv;
      while (argcount--) {
         fprintf( stderr, " \"%s\"", *argvec++ );
         }
      fprintf( stderr, "\n" );

      tloc = time( (long *)NULL );
      thetime = ctime(&tloc);
      fprintf( stderr, "thetime: %s\n",thetime );
   }

#ifdef MSDOS
    mcurdir = getcwd( s_mcurdir, sizeof(s_mcurdir) );
#else
   mcurdir = getcwd( s_mcurdir, 0 );
#endif
   chdir( spooldir );

   /* get sequence number */
   mkfilename( tfilename, confdir, SFILENAME );

    if ( debuglevel > 4 )
       fprintf( stderr, "pcmail: opening %s\n", tfilename ); /* */

   tempfile = FOPEN( tfilename, "r", 't' );
   if (tempfile != (FILE *)NULL) {
      fscanf( tempfile, "%ld", &sequence );
      fclose( tempfile );
   }
    else {
       fprintf( stderr, "pcmail: can't find %s file, creating\n",
                tfilename );
       sequence = 1;   /* start at 1 */
    };

   /* update sequence number */
   if ( debuglevel > 5 )
      fprintf( stderr, "pcmail: new sequence # %ld\n", sequence );

   tempfile = FOPEN( tfilename, "w", 't' );
   if (tempfile != (FILE *)NULL) {
      fprintf( tempfile, "%ld\n", sequence+1 );
      fclose( tempfile );
   }

   /* open a temporary file */
   /* sprintf( tfilename, TFILENAME, sequence ); */
    sprintf( miscbuff, TFILENAME, sequence );
    mkfilename( tfilename, tempdir, miscbuff );

    if ( debuglevel > 5 )
       fprintf( stderr, "pcmail: opening %s\n", tfilename );

   tempfile = FOPEN( tfilename, "w", 'b' );
    if (tempfile == (FILE *)NULL)  {
      fprintf( stderr, "pcmail: can't open %s\n", tfilename );
      exit(1);
   }

   /* copy stdin to tempfile, counting content lines and bytes */
   header = 1;
   while (fgets( buf, 512, stdin ) != (char *)NULL) {
      if (header != 0) {
         if (strlen( buf ) == 1) {
            header = 0;
            fprintf( tempfile, "\n" );
            continue;
         }
         else if (strchr( buf, ':' ) == NULL) {
            header = 0;
            fprintf( tempfile, "\n" );
         }
      }
      if (header == 0) {
         lines++;
         bytes += strlen( buf );
      }
      fputs( buf, tempfile );
   }
#ifndef RMAIL
   /* copy stdin to tempfile, counting content lines and bytes */
   /* get signature */
   mkfilename( mfilename, home, SIGFILE );

   if (debuglevel > 4)
       fprintf( stderr, "pcmail: opening sigfile %s\n", mfilename );
   mailfile = FOPEN( mfilename, "r", 't' );
   if (mailfile != (FILE *)NULL) {
      fputs( "\n--\n", tempfile );
      while (fgets( buf, 512, mailfile ) != (char *)NULL) {
         lines++;
         bytes += strlen( buf );
         fputs( buf, tempfile );
      }
      fclose( mailfile );
    }
#endif

    fclose( tempfile );

   if ( debuglevel > 4 ) {
      fprintf( stderr, "pcmail: stdin copied to tmp %ld %ld\n",
                    bytes, lines );
       fprintf( stderr, "pcmail: args %d\n", argc );
   }

   /* loop on args, copying to appropriate postbox,
      do remote only once
      remote checking is done empirically, could be better
   */
   remotes[0] = '\0';


#ifndef RMAIL
   if ( strcmp( argv[1], "-s" ) == SAME ) {
      argv++;argv++;
      argc--;argc--;
      if ( argc == 0 )
         return( -1 );
      strcpy( Subject, *argv );
      }
#endif
   argcount = argc;
   argvec = argv;

   while (--argcount > 0) {
      argvec++;
      if ( debuglevel > 5 )
         fprintf( stderr, "pcmail: arg# %d\t%s\n",
                     argcount, *argvec );

      if (
         (strchr( *argvec, '!' ) != SAME) ||
         (strchr( *argvec, '@' ) != SAME) ||
         (strchr( *argvec, '%' ) != SAME)
         ) {
         if ( debuglevel > 5 )
            fprintf( stderr, "pcmail: send to remote\n" );

         s1 = strlen( remotes );
         s2 = strlen( *argvec );

         /* can we cram one more address on line */
         if ( s1 > 0 && (s1 + s2 + 1) > 128 ) {
            /* dump it then, to bad */
            sendone( argc, argv, remotes, TRUE, __LINE__ );
            remotes[0] = '\0';
         }

         /* add *arvgvec to list of remotes */
         strcat( remotes, " " );
         strcat( remotes, *argvec );

      }
      else {
         if ( debuglevel > 5 )
            fprintf( stderr, "pcmail: calling sendone %s\n",
                     *argvec );

         sendone( argc, argv, *argvec, FALSE, __LINE__);
      }

   }
   /* dump remotes if necessary */
   if ( strlen( remotes ) > 0 )
      sendone( argc, argv, remotes, TRUE, __LINE__ );

/* I don't understand why the next block is needed... */
/* so I'll take it out.... */
#ifdef not_defined
#ifndef RMAIL

   mkfilename( mailsent, home, COPYFILE );
   if ( debuglevel > 4 )
      fprintf( stderr, "pcmail: copfile = %s\n", mailsent );
   sendone( argc, argv, mailsent, FALSE, __LINE__);

#endif
#endif
   unlink( tfilename );
   chdir( mcurdir );
   exit(0);
}


/*char fpat1[] = "%c.%.7s%04ld"; */ /* was... - GTOAL */
char fpat1[] = "%c_%.5s%03ld";
char fpat2[] = "S %s %s %s - %s 0666 %s";


/* sendone copies file plus headers to appropriate postbox
   NB. we do headers here to allow flexibility later, for example
   in being able to do bcc, per host service processing etc.
*/
sendone( argc, argv, address, remote, line )
char **argv;
int argc;
char *address;
{
   register char    *cp;
   char   icfilename[32];      /* local C. copy file */
   char   ixfilename[32];      /* local X. xqt file */
   char   idfilename[32];      /* local D. data file */
   char   rxfilename[32];      /* remote X. xqt file */
   char   rdfilename[32];      /* remote D. data file */
    char   tmfilename[32];      /* temporary storage */
#ifdef MSDOS
    char   cixfilename[32];      /* canonical ixfilename */
    char   cidfilename[32];      /* canonical idfilename */
#endif
   if ( debuglevel > 5 )
       fprintf( stderr, "pcmail: sendone called from line %d\n", line );
    if ( remote ) {
       /* sprintf all required file names */
      sprintf( tmfilename, fpat1, 'C', mailserv, sequence );
      importpath( icfilename, tmfilename );
#ifdef MSDOS
       sprintf( cidfilename, fpat1, 'D', mailserv, sequence );
      importpath( idfilename, cidfilename );
      sprintf( cixfilename, fpat1, 'D', nodename, sequence );
       importpath( ixfilename, cixfilename );
#else
      sprintf( tmfilename, fpat1, 'D', mailserv, sequence );
      importpath( idfilename, tmfilename );
      sprintf( tmfilename, fpat1, 'D', nodename, sequence );
      importpath( ixfilename, tmfilename );
#endif
      sprintf( rdfilename, fpat1, 'D', nodename, sequence );
      sprintf( rxfilename, fpat1, 'X', nodename, sequence );
    }
    else {
      /* postbox file name */
       if ( index( address, SEPCHAR ) == (char *)NULL )
         mkfilename( idfilename, maildir, address );
      else
         strcpy( idfilename, address );
   }

   if ( debuglevel > 5 )
       fprintf( stderr, "pcmail: sendone: %s\n", idfilename );

   if ( remote == FALSE ) {
      if ( debuglevel > 5 )
         fprintf( stderr, "pcmail: sendone: check for remote\n" );
      /* check for forwarding */
      if ( (mailfile = FOPEN( idfilename, "r", 'b' )) != (FILE *)NULL ) {
         cp = fgets( buf, BUFSIZ, mailfile );
         fclose( mailfile );
         if (cp != (char *)NULL)
            if (strncmp( buf, FORWARD, 10 ) == 0) {
               strcpy( buf, buf+11 );
               return( sendone( argc, argv, buf, FALSE, __LINE__ ) );
            }
      }
   }

   /* open mailfile */
   if ( (mailfile = FOPEN( idfilename, "a", 'b' )) == (FILE *)NULL ) {
      fprintf( stdout, "pcmail: cannot append to %s at line %d\n", idfilename, __LINE__ );
      return( 0 );
   }

   if ( debuglevel > 5 )
      fprintf( stderr, "pcmail: append to mailfile\n" );

   tloc = time( (long *)NULL );
   thetime = ctime(&tloc);
    (void)strcpy(chartime, thetime);   /* make our own copy */
    thetime = chartime;   /* and work with our own copy */
   thetime[strlen(thetime)-1] = '\0';

#ifdef RMAIL
   fprintf( mailfile, "From uucp %s", thetime );
   fputc( '\012', mailfile );
   fprintf( mailfile, "Received: by %s (pcmail) %s", domain, thetime );
   fputc( '\012', mailfile );
#else /* RMAIL */
   fprintf( mailfile, "From %s %s", mailbox, thetime );
   if ( remote )
      fprintf( mailfile, " remote from %s", nodename );
   fputc( '\012', mailfile );
   fprintf( mailfile, "Received: by %s (pcmail) %s", domain, thetime );
   fputc( '\012', mailfile );
   fprintf( mailfile, "Date: %s", thetime );
   fputc( '\012', mailfile );
   /* add Date:, From: and Message-ID: headers */
   fprintf( mailfile, "From: %s <%s@%s>", name, mailbox, domain );
   fputc( '\012', mailfile );
   fprintf( mailfile, "Message-ID: <%ld@%s>", sequence, domain );
   fputc( '\012', mailfile );
   /* add To: headers */
   while (--argc > 0) {
      fprintf( mailfile, "To: %s", *++argv );
      fputc( '\012', mailfile );
   }
   if ( strlen( Subject ) > 0 ) {
      fprintf( mailfile, "Subject: %s", Subject );
      fputc( '\012', mailfile );
   }
#ifdef PCMAIL
   /* add Message-Lines: and Content-Length: headers */
   fprintf( mailfile, "X-Message-Lines: %ld", lines );
   fputc( '\012', mailfile );
   fprintf( mailfile, "Content-Length: %ld", bytes );
   fputc( '\012', mailfile );
#endif /* PCMAIL */
#endif /* RMAIL */

   /* copy tempfile to postbox file */
   if (debuglevel > 4)
      fprintf( stderr, "pcmail: copy tempfile %s to %s\n",
                       tfilename, idfilename );
   tempfile = FOPEN( tfilename, "r", 'b' );
   if ( tempfile == (FILE *)NULL) {
      fprintf( stdout, "pcmail: can't re-open %s\n", tfilename );
      return( 0 );
   }
   while (fgets( buf, 512, tempfile ) != (char *)NULL) {
      if ( strncmp( buf, "From ", 5 ) == 0 )
         fputc( '>', mailfile );
      cp = &buf[ strlen(buf)-1 ];
      if ( *cp == '\n' )
         *cp = '\0';
      fputs( buf, mailfile );
      fputc( '\012', mailfile );
    }

   /* close files */
   fclose( mailfile );
   fclose( tempfile );

   /* all done unless going to remote via uucp */
   /* must create the job control files */
   if ( remote == TRUE ) {

      /* create remote X xqt file */
      mailfile = FOPEN( ixfilename, "w", 'b' );
      if    (mailfile == (FILE *)NULL) {
         fprintf( stdout, "pcmail: cannot append to %s at line %d\n", ixfilename, __LINE__ );
         return( 0 );
      }
      fprintf( mailfile, "U %s %s", uucp, nodename );
      fputc( '\012', mailfile );
      fprintf( mailfile, "F %s", rdfilename );
      fputc( '\012', mailfile );
      fprintf( mailfile, "I %s", rdfilename );
      fputc( '\012', mailfile );
      fprintf( mailfile, "C rmail %s", address );
      fputc( '\012', mailfile );
      fclose( mailfile );

      /* create local C copy file */
      mailfile = FOPEN( icfilename, "w", 't' );
      if    (mailfile == (FILE *)NULL) {
         fprintf( stdout, "pcmail: cannot append to %s at line %d\n", icfilename, __LINE__);
         return( 0 );
      }

#ifdef MSDOS
       fprintf( mailfile, fpat2, cidfilename, rdfilename,
                uucp, cidfilename, uucp );
       fputc( '\012', mailfile );
       fprintf( mailfile, fpat2, cixfilename, rxfilename,
                uucp, cixfilename, uucp );
       fputc( '\012', mailfile );
#else
      fprintf( mailfile, fpat2, idfilename, rdfilename,
               uucp, idfilename, uucp );
      fputc( '\012', mailfile );
      fprintf( mailfile, fpat2, ixfilename, rxfilename,
               uucp, ixfilename, uucp );
      fputc( '\012', mailfile );
#endif
      fclose( mailfile );

   } /* if ( remote == TRUE ) */

   return( 1 );
}

#ifndef AMIGA
#ifdef RMAIL
rnews(argc, argv)
int argc;
char *argv[];
{
   struct tm   *thetm;
   char   filename[132];
   char   format[128];
   FILE    *f;
   char   buf[BUFSIZ];

   static int count = 0;

   tloc = time( (long *)NULL );
   thetime = ctime(&tloc);
   tloc = time( (long *)NULL );

   thetm = localtime( &tloc );

   /* mkfilename( format, spooldir, NEWSDIR );   */
   sprintf( filename, NEWSDIR,
      thetm->tm_year % 100, thetm->tm_mon,
      thetm->tm_mday, thetm->tm_hour,
      thetm->tm_min,  thetm->tm_sec,  count
      );

   count++;

   if ( debuglevel > 5 )
      fprintf( stderr, "rnews: %s\n", filename );

   if ( (f = FOPEN( filename, "w", 't' )) == (FILE *)NULL ) {
      fprintf( stderr, "rnews: can't open %s %d\n", filename, errno );
      return( -1 );
   }

   while ( fgets( buf, BUFSIZ, stdin ) != (char *)NULL )
      fputs( buf, f );

   fclose( f );
}

#endif /* RMAIL */
#endif /* AMIGA */
