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 >
Wrap
C/C++ Source or Header
|
1987-10-28
|
14KB
|
601 lines
/* 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 );
}
mcurdir = getcwd( s_mcurdir, 0 );
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 );
/* 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 sequence number */
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 ( remote ) {
/* sprintf all required file names */
sprintf( tmfilename, fpat1, 'C', mailserv, sequence );
importpath( icfilename, tmfilename );
sprintf( tmfilename, fpat1, 'D', mailserv, sequence );
importpath( idfilename, tmfilename );
sprintf( tmfilename, fpat1, 'D', nodename, sequence );
importpath( ixfilename, tmfilename );
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 );
}
fprintf( mailfile, fpat2, idfilename, rdfilename,
uucp, idfilename, uucp );
fputc( '\012', mailfile );
fprintf( mailfile, fpat2, ixfilename, rxfilename,
uucp, ixfilename, uucp );
fputc( '\012', mailfile );
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