home *** CD-ROM | disk | FTP | other *** search
- /* 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
-
-
- */
-
- /*
- #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();
-
-
-
- main(argc, argv)
- 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 = 1;
-
- #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\ %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 );
- 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 );
- }
-
- }
- /* dump remotes if necessary */
- if ( strlen( remotes ) > 0 )
- sendone( argc, argv, remotes, TRUE );
-
- #ifndef RMAIL
-
- mkfilename( mailsent, home, COPYFILE );
- if ( debuglevel > 4 )
- fprintf( stderr, "pcmail: copfile = %s\n", mailsent );
- sendone( argc, argv, mailsent, FALSE );
-
- #endif
-
- unlink( tfilename );
- chdir( mcurdir );
- exit(0);
- }
-
-
- char fpat1[] = "%c.%.7s%04ld";
- 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 )
- 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 */
- #if MSDOS
- char cixfilename[32]; /* canonical ixfilename */
- char cidfilename[32]; /* canonical idfilename */
- #endif
- 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 ) );
- }
- }
- }
-
- /* open mailfile */
- if ( (mailfile = FOPEN( idfilename, "a", 'b' )) == (FILE *)NULL ) {
- fprintf( stdout, "pcmail: cannot append to %s\n", idfilename );
- 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\n", ixfilename );
- 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\n", icfilename );
- return( 0 );
- }
-
- #if 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 */
-
-
-