home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff319.lzh
/
CNewsSrc
/
uupc.lzh
/
uupc
/
pcmail.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-16
|
19KB
|
742 lines
/*
* $Id: pcmail.c,v 1.4 90/01/16 10:26:55 crash Exp Locker: crash $
*
* Copying and use of this program are controlled by the terms of the
* Free Software Foundations GNU Emacs General Public License.
*
* Copyright (C) 1987 Stuart Lynne
* Version 0.1 March 31/1987
*
* 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 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 environment variables are used:
* MAILBOX current user's mailbox, "crash"
* NAME current user's name, "Frank Edwards"
* DOMAIN domain of this machine, "ckctpa.UUCP"
* MAILDIR where is mail kept, ":usr/crash"
*
* 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
* RMAIL rmail
*/
#define ORGANIZATION "ComputerKnowledge Corp, Clearwater FL"
#ifndef lint
static char RCSid[] = "$Id: pcmail.c,v 1.4 90/01/16 10:26:55 crash Exp Locker: crash $";
#endif /* lint */
/*
# ifdef NOMAIN
# include "dcp.h"
# else
*/
# include <stdio.h>
# include "host.h"
/*
# endif
*/
#ifdef MSDOS
# define PC_FILENMS 1
#else
# ifdef AMIGA
# define PC_FILENMS 1
# ifdef MCH_AMIGA
# include <functions.h>
# else
# include <proto/exec.h>
# endif
# endif
#endif
FILE *FOPEN();
#define FORWARD "Forward to"
#define SBUFSIZ 124
FILE *mailfile;
FILE *tempfile;
char buf[BUFSIZ];
char miscbuff[100];
long lines = 0;
long bytes = 0;
long sequence = 0;
long tloc;
char chartime[26]; /* current time in ASCII */
char *thetime;
char tfilename[100];
char mfilename[100];
char mailsent[100];
int flag_rnews = FALSE; /* Flag for news posting instead of email */
int local = TRUE;
char remotes[BUFSIZ];
char uucp[] = "uucp";
extern char *getcwd();
extern int chdir();
extern void *malloc();
extern char *index();
extern char *rindex();
extern char *fgets();
extern 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 *progname; /* Holder for argv[0] for error messages */
char *mcurdir;
char s_mcurdir[BUFSIZ]; /* current directory path (save malloc call) */
main(argc, argv)
char *argv[];
{
long position;
register int header = 1;
register int amount;
register int argcount;
register char **argvec;
int remote;
int s1, s2;
progname = argv[0];
#ifndef NOMAIN
/* get environment var's */
HOSTINIT;
loadenv();
if (argc <= 1) {
fprintf( stderr, "Usage: %s [-s subj] users\n", progname );
exit(1);
}
debuglevel = 1;
#endif
#ifdef RMAIL
local = FALSE;
#else
local = TRUE;
#endif
if ( debuglevel > 5 ) {
fprintf( stderr, "%s: argc %d ", progname, argc );
argcount = argc;
argvec = argv;
while (argcount--)
fprintf( stderr, " \"%s\"", *argvec++ );
fputc( '\n', stderr );
tloc = time( (long *)NULL );
thetime = ctime(&tloc);
fprintf( stderr, "thetime: %s\n",thetime );
}
#ifdef PC_FILENMS
getcwd( s_mcurdir, sizeof(s_mcurdir) );
#else
getcwd( s_mcurdir, 0 );
#endif
chdir( spooldir );
/* get sequence number */
mkfilename( tfilename, confdir, SFILENAME );
if ( debuglevel > 4 )
fprintf( stderr, "%s: opening %s\n", progname, tfilename ); /* */
tempfile = FOPEN( tfilename, "r", 't' );
if (tempfile != (FILE *)NULL) {
fscanf( tempfile, "%ld", &sequence );
fclose( tempfile );
} else {
fprintf( stderr,
"%s: can't find %s file, creating\n", progname, tfilename );
sequence = 1; /* start at 1 */
}
/* update sequence number */
if ( debuglevel > 5 )
fprintf( stderr, "%s: new sequence # %ld\n", progname, sequence );
tempfile = FOPEN( tfilename, "w", 't' );
if (tempfile != (FILE *)NULL) {
fprintf( tempfile, "%ld\n", sequence+1 );
fclose( tempfile );
}
s1 = sequence;
/* open a temporary file */
/* sprintf( tfilename, TFILENAME, sequence ); */
try_tmpfile_again:
sprintf( miscbuff, TFILENAME, sequence );
mkfilename( tfilename, tempdir, miscbuff );
if ( debuglevel > 5 )
fprintf( stderr, "%s: opening %s\n", progname, tfilename );
tempfile = FOPEN( tfilename, "w", 'b' );
if (tempfile == (FILE *)NULL) { /* got an error here somehow */
fprintf( stderr, "%s: can't open %s\n", progname, tfilename );
#ifdef FJE
if (++sequence < s1 + 100) /* Try more than once... */
goto try_tmpfile_again;
else
#endif /* FJE */
exit(1);
}
/* copy stdin to tempfile, counting content lines and bytes */
#ifndef RMAIL
if ( strcmp( argv[1], "-s" ) == SAME ) {
argv += 2;
argc -= 2;
if ( argc == 0 )
return( -1 );
strcpy( Subject, *argv );
}
# ifdef FJE /* Interactive Subject: line prompt */
else if (isatty( fileno(stdin) )) {
fputs("Subject: ", stderr);
fflush(stderr);
gets( Subject );
}
if (argc==2 && !strnicmp(argv[1], "rnews", 6)) /* same as stricmp() */
flag_rnews = TRUE; /* Posting an article instead of email */
# endif /* FJE */
#endif /* !RMAIL */
header = 1;
while (fgets( buf, sizeof(buf), stdin ) != (char *)NULL) {
if (header) {
char *tmp = buf;
while (isspace(*tmp)) tmp++;
if (strlen( tmp ) < 2) {
header = 0;
continue;
} else if (strchr( tmp, ':' ) == NULL) {
header = 0;
} else
header = storehdr( tmp );
}
if (!header) {
lines++;
bytes += strlen( buf );
fputs( buf, tempfile );
}
}
/* get signature */
#ifndef RMAIL
#ifdef FJE /* Different .signature if posting an article */
mkfilename( mfilename, home, flag_rnews ? POSTFILE : SIGFILE );
#else
mkfilename( mfilename, home, SIGFILE );
#endif /* !FJE */
if (debuglevel > 4)
fprintf( stderr, "%s: opening sigfile %s\n", progname, mfilename );
mailfile = FOPEN( mfilename, "r", 't' );
if (mailfile != (FILE *)NULL) {
fputs( "\n-----\n", tempfile );
bytes += 7;
while (fgets( buf, sizeof(buf), mailfile ) != (char *)NULL) {
lines++;
bytes += strlen( buf );
fputs( buf, tempfile );
}
fclose( mailfile );
}
#endif /* !RMAIL */
fclose( tempfile );
if ( debuglevel > 4 ) {
fprintf( stderr, "%s: stdin copied to tmp: %ld bytes %ld lines\n",
progname, bytes, lines );
fprintf( stderr, "%s: args %d\n", progname, argc );
}
/*
* loop on args, copying to appropriate postbox,
* do remote only once
* remote checking is done empirically, could be better
*/
remotes[0] = '\0';
argcount = argc;
argvec = argv;
while (--argcount > 0) {
argvec++;
if ( debuglevel > 5 )
fprintf( stderr,
"%s: arg# %d %s\n", progname, argcount, *argvec );
if (index( *argvec, '!' ) || index( *argvec, '@' ) ||
index( *argvec, '%' )) {
if ( debuglevel > 5 )
fprintf( stderr, "%s: send to remote\n", progname );
s1 = strlen( remotes );
s2 = strlen( *argvec );
/* can we cram one more address on line */
if ( s1 > 0 && (s1 + s2 + 1) > 128 ) {
/* dump it then, too 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,
"%s: calling sendone %s\n", progname, *argvec );
sendone( argc, argv, *argvec, flag_rnews );
}
}
/* dump remotes if necessary */
if ( strlen( remotes ) > 0 )
sendone( argc, argv, remotes, TRUE );
#ifndef RMAIL
#ifdef FJE
if (!flag_rnews) /* Only record if email, not a posting */
#endif /* FJE */
{
mkfilename( mailsent, home, COPYFILE );
if ( debuglevel > 4 )
fprintf( stderr, "%s: copfile = %s\n", progname, mailsent );
sendone( argc, argv, mailsent, FALSE );
}
#endif /* !RMAIL */
unlink( tfilename );
chdir( s_mcurdir );
exit(0);
}
static struct _header {
char *hdr; /* Header text */
char *text; /* Text found in letter for this header */
} headers[] = {
{ "Path:", NULL },
{ "Newsgroups:", NULL },
{ "Followup-To:", NULL },
{ "Organization:", NULL },
{ "Summary:", NULL },
{ "Received:", NULL },
{ "From:", NULL },
{ "Date:", NULL },
{ "Subject:", NULL },
{ "Message-ID:", NULL },
{ NULL, NULL } };
#define H_PATH 0
#define H_GRPS 1
#define H_FOLL 2
#define H_ORG 3
#define H_SUMM 4
#define H_FROM 5
#define H_RECV 6
#define H_DATE 7
#define H_SUBJ 8
#define H_MSG 9
static struct _header *findhdr(str)
register char *str;
{
register struct _header *hdr = headers;
while (hdr->hdr && strcmp(hdr->hdr, str))
hdr++;
return( hdr->hdr ? hdr : (struct _header *) 0);
}
static int storehdr(str)
register char *str;
{
char ch;
register char *tmp = index(str, ':');
register struct _header *hdr;
ch = *++tmp;
*tmp++ = '\0';
if (hdr = findhdr(str)) {
while (isspace(*tmp)) tmp++;
if (hdr->text = (char *) malloc(strlen(tmp) + 1)) {
strcpy(*hdr, str);
return( TRUE );
}
}
tmp[-1] = ch; /* Either header not found or malloc() failed */
return( FALSE );
}
static char *saveprintf(fmt, args)
char *fmt;
int args;
{
register char *mem;
if (mem = (char *) malloc(512))
vsprintf(mem, fmt, &args);
return( mem );
}
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 */
#ifdef PC_FILENMS
char cixfilename[32]; /* canonical ixfilename */
char cidfilename[32]; /* canonical idfilename */
#endif
#ifdef FJE /* Print the headers from headers[] */
register struct _header *start;
#endif /* FJE */
if ( remote ) {
/* sprintf all required file names */
sprintf( tmfilename, fpat1, 'C', mailserv, sequence );
importpath( icfilename, tmfilename );
#ifdef PC_FILENMS
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 ); /* Can't get here, can it!? */
}
if ( debuglevel > 5 )
fprintf( stderr, "%s: sendone: %s\n", progname, idfilename );
if (!remote) {
if ( debuglevel > 5 )
fprintf( stderr, "%s: sendone: check for remote\n", progname );
/* check for forwarding */
if ( (mailfile = FOPEN( idfilename, "r", 'b' )) != (FILE *)NULL ) {
cp = fgets( buf, BUFSIZ, mailfile );
fclose( mailfile );
if (cp && !strncmp( buf, FORWARD, 10 )) {
strcpy( buf, buf+11 );
return( sendone( argc, argv, buf, FALSE ) );
}
}
}
/* open mailfile */
if ( (mailfile = FOPEN( idfilename, "a+", 'b' )) == (FILE *)NULL ) {
fprintf( stdout, "%s: cannot append to %s\n", progname, idfilename );
return( 0 );
}
if ( debuglevel > 5 )
fprintf( stderr, "%s: append to mailfile\n", progname );
tloc = time( (long *)NULL );
(void) strcpy(thetime = chartime, ctime(&tloc)); /* our own copy */
thetime[strlen(thetime)-1] = '\0'; /* remove '\n' */
#ifdef RMAIL
fprintf( mailfile, "From uucp %s", thetime );
fputc( '\012', mailfile );
fprintf(mailfile, "Received: by %s (%s) %s", domain, progname, thetime);
fputc( '\012', mailfile );
#else /* !RMAIL */
# ifdef FJE
if (flag_rnews) {
start = &headers[H_PATH];
if (!headers[H_PATH].text)
headers[H_PATH].text = nodename;
if (!headers[H_ORG].text)
headers[H_ORG].text = ORGANIZATION;
headers[H_RECV].text = NULL;
} else {
start = &headers[H_RECV];
headers[H_PATH].text = NULL;
headers[H_ORG].text = NULL;
if (!headers[H_RECV].text)
headers[H_RECV].text = saveprintf("Received: by %s (%s) %s\012",
domain, progname, thetime);
fprintf( mailfile, "From %s %s", mailbox, thetime );
if (remote) fprintf( mailfile, " remote from %s", nodename );
fputc( '\012', mailfile );
}
if (!headers[H_FROM].text)
#ifdef KLUDGE_FROM_LINE
/*
* From: Frank J. Edwards <ckctpa!crash@boake2>\012",
* name, nodename, mailbox, mailserv
*/
headers[H_FROM].text = saveprintf("%s <%s!%s@%s>\012",
name, nodename, mailbox, mailserv);
#else /* !KLUDGE_FROM_LINE */
/*
* From: %s <%s@%s>\012", name, mailbox, domain
*/
headers[H_FROM].text = saveprintf("%s <%s@%s>\012",
name, mailbox, domain);
#endif /* KLUDGE_FROM_LINE */
if (!headers[H_DATE].text)
headers[H_DATE].text = saveprintf("%s\012", thetime);
if (!headers[H_MSG].text)
headers[H_MSG].text = saveprintf("<%ld@%s>\012", sequence, domain );
if (!headers[H_SUBJ].text)
headers[H_SUBJ].text = Subject;
for ( ; start->hdr; start++)
if (start->text)
fprintf(mailfile, "%s %s\012", start->hdr, start->text);
if (!flag_rnews) {
/* add To: headers */
while (--argc > 0)
fprintf( mailfile, "To: %s\012", *++argv );
}
# else /* FJE */
fprintf( mailfile, "From %s %s", mailbox, thetime );
if ( remote )
fprintf( mailfile, " remote from %s", nodename );
fputc( '\012', mailfile );
fprintf( mailfile, "Received: by %s (%s) %s\012",
domain, progname, thetime);
fprintf( mailfile, "Date: %s\012", thetime );
/* "From: %s <%s@%s>\012", name, mailbox, domain */
fprintf( mailfile, "From: %s <%s@%s>\012", name, mailbox, domain );
fprintf( mailfile, "Message-ID: <%ld@%s>\012", sequence, domain );
/* add To: headers */
while (--argc > 0)
fprintf( mailfile, "To: %s\012", *++argv );
if ( strlen( Subject ) > 0 ) {
fprintf( mailfile, "Subject: %s", Subject );
fputc( '\012', mailfile );
}
# endif /* !FJE */
# 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 */
fputc( '\012', mailfile ); /* Blank line between hdrs & message */
#endif /* !RMAIL */
/* copy tempfile to postbox file */
if (debuglevel > 4)
fprintf( stderr, "%s: copy tempfile %s to %s\n",
progname, tfilename, idfilename );
tempfile = FOPEN( tfilename, "r", 'b' );
if ( tempfile == (FILE *)NULL) {
fprintf( stdout, "%s: can't re-open %s\n", progname, tfilename );
return( 0 );
}
while (fgets( buf, 512, tempfile ) != (char *)NULL) {
if ( strncmp( buf, "From ", 5 ) == 0 )
fputc( '>', mailfile );
if (cp = index(buf, '\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 ) {
/* create remote X xqt file */
mailfile = FOPEN( ixfilename, "w", 'b' );
if (mailfile == (FILE *)NULL) {
fprintf( stdout,
"%s: cannot append to %s\n", progname, ixfilename );
return( 0 );
}
fprintf( mailfile, "U %s %s\012", uucp, nodename );
fprintf( mailfile, "F %s\012", rdfilename );
fprintf( mailfile, "I %s\012", rdfilename );
cp = address;
#ifdef FJE
while (*cp && isspace(*cp))
cp++;
# if 0
if ( !strncmp(cp, mailserv, first = strlen(mailserv)) ) {
if ( cp[ first ] == '!' )
cp += first + 1;
}
# endif
#endif /* FJE */
fprintf(mailfile, flag_rnews ? "C rnews\012" : "C rmail %s\012",cp);
fclose( mailfile );
/* create local C copy file */
mailfile = FOPEN( icfilename, "w", 't' );
if (mailfile == (FILE *)NULL) {
printf("%s: cannot append to %s\n", progname, icfilename );
return( 0 );
}
#ifdef PC_FILENMS
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 /* !PC_FILENMS */
fclose( mailfile );
}
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);
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 */
/* !AMIGA */