Path: utzoo!mnetor!uunet!husc6!tut.cis.ohio-state.edu!rutgers!iuvax!pur-ee!j.cc.purdue.edu!ain From: ain@j.cc.purdue.edu (Patrick White) Newsgroups: comp.sources.amiga Subject: uupc version 1.1 (part 2 of 3) Message-ID: <6737@j.cc.purdue.edu> Date: 21 Mar 88 05:10:15 GMT Organization: PUCC Land, USA Lines: 2640 Keywords: part 2 of 3, version 1.1, uupc, uncompiled Approved: ain@j.cc.purdue.edu (Pat White) Program Name: uupc version 1.1 (part 2 of 3) Submitted By: Johan Widen Summary: Implements uucp for the Amiga -- allows your Amiga to become a uupc site for mail (and news?). Poster Boy: Pat White (ain@j.cc.purdue.edu) Uncompiled. NOTES: Didn't try compiling it. Converted the origional zoo to shars so docs, binaries & sources could be separated. I'm pretty sure this would allow one to receive news, but I remember something in the docs about it not having been tested from when I was quickly scanning them... so I'm not too sure on this. Rob has been playing with it for a while and says it works. -- Pat White (co-moderator comp.sources/binaries.amiga) UUCP: j.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421 U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906 ======================================== # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # genv.c # genv.h # host.h # lib.c # lmail.c # mail.c # mailhost.c # mlib.c # ndir.c # ndir.h # pccp.c # This archive created: Sat Mar 19 01:41:50 1988 # By: Patrick White (PUCC Land, USA) echo shar: extracting genv.c '(7740 characters)' cat << \SHAR_EOF > genv.c /* genv.c copyright (C) 1987 Jeff Lydiatt Copying and use of this program are controlled by the terms of the Free Software Foundations GNU Emacs General Public License. version 0.1 10 July 87 */ #include #include #include "genv.h" extern int debuglevel; /* Environment variables are in file "PROFILE" */ #define PROFILE ":usr/lib/uucp/profile" #define SAME 0 #define MAXLINE 255 #define DMAILBOX "mailbox" #define DNAME "noname" #define DDOMAIN "pc.uucp" #define DMAILDIR ":usr/spool/mail" #define DHOME ":usr/noname" #define DCONFDIR ":usr/lib/uucp" #define DSPOOLDIR ":usr/spool/uucp" #define DLOGDIR ":usr/spool/uucp" #define DPUBDIR ":usr/spool/uucppublic" #define DNEWSDIR ":usr/spool/rnews" #define DTEMPDIR "RAM:T" #define DMAILSERVICE "host" #define DNODENAME "noname" #define DDEVICE "CON:" #define DSPEED "1200" #define DPAGESIZE "24" #define DTIMEZONE "+0100" #define TFILENAME "tmpfile" #define FILENAME "%s/%s" char *name = NULL; char *mailbox = NULL; char *home = NULL; char *domain = NULL; char *maildir = NULL; char *confdir = NULL; char *spooldir = NULL; char *logdir = NULL; char *pubdir = NULL; char *mailserv = NULL; char *nodename = NULL; char *device = NULL; char *speed = NULL; char *tempdir = NULL; char *newsdir = NULL; int pagesize = 24; static char *pagesizeString = NULL; char *timeZone = NULL; /*--------------------------------------------------------------*/ /* getsym: get next symbol from file f. f already open */ /*--------------------------------------------------------------*/ #define ID 1001 #define DELIM 1002 #define STR 1003 #define EOL 1004 #define OTHER 1005 #define UNKNOWN -1000 static int getsym( f, sym ) FILE *f; char *sym; { /* Simple non reentrant, non reuseable get next symbol from file f */ /* Valid symbols are: Type Symbol Returned Comment ID any valid c identifier. DELIM '=' an equal sign. STR a string anything between "" or ''. EOL '\n' a newline. EOF the end of file character. OTHER a character anything else. Comments begin with # and are delimited by an end of line */ static int lastchar = UNKNOWN; int c, delim; /* strip leading white space */ if ( lastchar != UNKNOWN ) c = lastchar; else c = fgetc( f ); while ( c == ' ' || c == '\t' ) c = fgetc( f ); lastchar = UNKNOWN; /* Comments are '#' delimited by EOL character */ if ( c == '#' ) while ( c != '\n' && c != EOF ) c = fgetc( f ); if ( c == EOF ) /* End of file? */ return EOF; if ( c == '\n' ) /* End of Line? */ { strcpy( sym, "\n" ); return EOL; } if ( c == '=' ) /* Delimiter '='? */ { strcpy( sym, "=" ); return DELIM; } if ( c == '\"' || c == '\'' )/* String ? */ { delim = c; while ( (c = fgetc( f )) != delim && c != EOF && c != '\n' ) *sym++ = c; *sym = '\0'; c = fgetc( f ); return STR; } if ( isalpha( c ) ) /* Identifier ? */ { *sym++ = c; while ( ( c = fgetc( f )) == '_' || isalnum(c) ) *sym++ = c; *sym = '\0'; lastchar = c; return ID; } *sym++ = c; *sym = '\0'; return OTHER; } /*--------------------------------------------------------------*/ /* xmalloc: Just alloc with die on allocation failure */ /*--------------------------------------------------------------*/ static char *xmalloc( size ) unsigned int size; { char *malloc(); register char *p; if ( (p = malloc( size )) != NULL ) return p; fprintf( stderr, "Genv.c: Can't allocated %u bytes\n", size ); exit( NULL ); } /*--------------------------------------------------------------*/ /* setenv: insert an environment variable into my list */ /*--------------------------------------------------------------*/ struct environment { struct environment *next; char *name; char *value; }; typedef struct environment ENV; static ENV *envList = NULL; static void setenv( var, value ) char *var; char *value; { register ENV *envframe; envframe = (ENV *) xmalloc( sizeof( ENV )); envframe->name = xmalloc( strlen(var)+1 ); envframe->value = xmalloc( strlen(value)+1 ); envframe->next = envList; envList = envframe; strcpy( envframe->name, var ); strcpy( envframe->value, value); } /*--------------------------------------------------------------*/ /* getenv: get pointer to value of environment variable */ /*--------------------------------------------------------------*/ static char *getenv( var ) char *var; { register ENV *list; for ( list = envList; list != (ENV *)NULL; list = list->next ) if ( strcmp( var, list->name ) == SAME ) return list->value; return NULL; } /*--------------------------------------------------------------*/ /* readenv: read environment from a file. */ /*--------------------------------------------------------------*/ static void readenv() { FILE *f; int symval; char name[MAXLINE+1], value[MAXLINE+1]; if ( (f = fopen( PROFILE, "r" )) == NULL ) { fprintf( stderr, "Can't open profile file \"%s\"\n", PROFILE ); exit( NULL ); } /* File is layed out as follows: '=' | # comment.... */ while ( (symval = getsym( f, name )) != EOF ) { /* Skip over any comment lines */ while ( symval == EOL ) symval = getsym( f, name ); if ( symval == EOF ) break; if ( symval != ID ) { fprintf( stderr, "Bad environment variable name %s\n", name ); exit( NULL ); } if ( (symval = getsym( f, value )) != DELIM ) { fprintf( stderr, "Missing '=' in environment file\n" ); exit( NULL ); } if ( (symval = getsym( f, value )) != ID && symval != STR ) { fprintf( stderr, "missing value in environment file\n"); exit( NULL ); } setenv( name, value ); } fclose( f ); } /*--------------------------------------------------------------*/ /* exitenv: free that memory when done! */ /*--------------------------------------------------------------*/ void exitenv() { register ENV *p, *q; for ( p = envList; p != NULL; p = q ) { free( p->name ); free( p->value); q = p->next; free( p ); } envList = NULL; } static void genv(thename, envname, dflt) char **thename; char *envname; char *dflt; { if ((*thename = getenv( envname )) == NULL) { fprintf( stderr, "genv: %s not found, using %s\n", envname, dflt ); *thename = dflt; } /* fprintf( stderr, "genv: %s \"%s\"\n", envname, *thename ); /**/ } void loadenv() { readenv(); /* read the profile from a file */ /* get environment var's */ genv( &name, NAME, DNAME ); genv( &mailbox, MAILBOX, DMAILBOX ); genv( &home, HOME, DHOME ); genv( &domain, DOMAIN, DDOMAIN ); genv( &maildir, MAILDIR, DMAILDIR ); genv( &confdir, CONFDIR, DCONFDIR ); genv( &spooldir, SPOOLDIR, DSPOOLDIR ); genv( &logdir, LOGDIR, DLOGDIR ); genv( &pubdir, PUBDIR, DPUBDIR ); genv( &mailserv, MAILSERVICE, DMAILSERVICE ); genv( &nodename, NODENAME, DNODENAME ); genv( &device, DEVICE, DDEVICE ); genv( &speed, SPEED, DSPEED ); genv( &tempdir, TEMPDIR, DTEMPDIR ); genv( &newsdir, NEWSDIR2, DNEWSDIR ); genv( &pagesizeString, PAGESIZE, DPAGESIZE ); pagesize = atoi(pagesizeString); genv( &timeZone, TIMEZONE, DTIMEZONE ); } void mkfilename( filename, dirname, name ) char * filename; char * dirname; char * name; { sprintf( filename, FILENAME, dirname, name ); if(debuglevel > 4) fprintf( stderr, "New filename %s\n", filename ); /**/ } #ifdef TEST main() { register ENV *p; loadenv(); for ( p = envList; p != NULL; p = p->next ) fprintf( stderr, "Name=\"%s\" value=\"%s\"\n", p->name, p->value ); } #endif SHAR_EOF if test 7740 -ne "`wc -c genv.c`" then echo shar: error transmitting genv.c '(should have been 7740 characters)' fi echo shar: extracting genv.h '(1960 characters)' cat << \SHAR_EOF > genv.h /* genv.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 environment variables The following evironment variables are defined: MAILBOX current user's mailbox, "sl" NAME current user's name, "Stuart Lynne" DOMAIN domain of this machine, "mac.van-bc.can" MAILDIR where mail is kept, "/usr/mail" CONFDIR where config data is kept, "/usr/lib/uucp" SPOOLDIR where spooled files are "/usr/spool/uucp" LOGDIR where log file are placed "/usr/spool/uucp" PUBDIR public spool directory "/usr/spool/uucppublic" NEWSDIR news directory "/usr/spool/news" TEMPDIR where temp files are created "/tmp" HOME where uses private files are "/usr/sl" MAILSERVICE who do we send remote mail "van-bc" NODENAME what is our local nodename "slmac" DEVICE what is the default device ".a" SPEED what is the default speed "1200" PAGESIZE lines per page in mail pager "24" TIMEZONE to be appended to Date: field "+0100" */ #define MAILBOX "MAILBOX" #define NAME "NAME" #define DOMAIN "DOMAIN" #define MAILDIR "MAILDIR" #define HOME "HOME" #define CONFDIR "CONFDIR" #define SPOOLDIR "SPOOLDIR" #define LOGDIR "LOGDIR" #define PUBDIR "PUBDIR" #define NEWSDIR2 "NEWSDIR" #define TEMPDIR "TEMPDIR" #define MAILSERVICE "MAILSERVICE" #define NODENAME "NODENAME" #define DEVICE "DEVICE" #define SPEED "SPEED" #define PAGESIZE "PAGESIZE" #define TIMEZONE "TIMEZONE" extern char *mailbox; extern char *name; extern char *domain; extern char *maildir; extern char *home; extern char *confdir; extern char *spooldir; extern char *logdir; extern char *pubdir; extern char *tempdir; extern char *mailserv; extern char *nodename; extern char *device; extern char *speed; extern char *newsdir; extern int pagesize; extern char *timeZone; void loadenv(); void mkfilename(); SHAR_EOF if test 1960 -ne "`wc -c genv.h`" then echo shar: error transmitting genv.h '(should have been 1960 characters)' fi echo shar: extracting host.h '(829 characters)' cat << \SHAR_EOF > host.h /* Amiga.h Amiga version */ #include #include #include #ifndef MANX #include #include #endif #ifndef AMIGA #define AMIGA 1 #endif #define SAME 0 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define TFILENAME "tmpfile.%.7d" #define SFILENAME "SEQF" #define SEPCHAR '/' /* path separator */ #define SIGFILE ".signature" /* file containing signature */ #define COPYFILE "mail.sent" /* copy of sent mail */ #define BREAK /* BREAK command is defined in "systems" */ #define HOSTINIT /* name of function used to initialize */ #define FILEMODE(f) #define CALLFILE "C.%s" #define XQTFILE "X.%s" #ifndef MANX #define index strchr #define rindex strrchr #endif #include "genv.h" extern char * fgets(); extern char * index(); extern int debuglevel; SHAR_EOF if test 829 -ne "`wc -c host.h`" then echo shar: error transmitting host.h '(should have been 829 characters)' fi echo shar: extracting lib.c '(2757 characters)' cat << \SHAR_EOF > lib.c /* lib.c */ #include #include #include #include #include #include "host.h" #ifndef NULL #define NULL 0L #endif char *index(); char *rindex(); MKDIR( path ) char * path; { char * cp = path; if ( *cp == '\0' ) return( 0 ); /* see if we need to make any intermediate directories */ while ( ( cp = index( cp, '/' ) ) != (char *) NULL ) { *cp = '\0'; mkdir( path ); *cp = '/'; cp++; } /* make last dir */ return( mkdir( path ) ); } CHDIR( path ) char * path; { char * cp = path; if ( *cp == '\0' ) return( 0 ); MKDIR( path ); /* change to last directory */ return( chdir( path ) ); } FILE * FOPEN( name, mode, ftype ) char * name; char * mode; char ftype; { char * last; FILE * results; /* are we opening for write or append */ FILEMODE( ftype ); results = fopen( name, mode ); if ( results != (FILE *) NULL || *mode == 'r' ) return( results ); /* are we opening in sub-directory */ last = rindex( name, '/' ); /* lets just verify that all sub-dir's exist */ if ( last != (char *) NULL ) { *last = '\0'; MKDIR( name ); *last = '/'; } /* now try open again */ return( fopen( name, mode )); } int CREAT( name, mode, ftyp ) char * name; int mode; char ftyp; { char * last; int results; /* are we opening for write or append */ FILEMODE( ftyp ); results = creat( name, mode ); if ( results != -1 ) return( results ); /* are we opening in sub-directory */ last = rindex( name, '/' ); /* lets just verify that all sub-dir's exist */ if ( last != (char *) NULL ) { *last = '\0'; MKDIR( name ); *last = '/'; } /* now try open again */ return( creat( name, mode ) ); } extern FILE *logfile; extern int debuglevel; extern int remote; #define MASTER 1 int getargs( line, flds ) char *line; char **flds; { int i = 0; while ( (*line != '\0') && (*line != '\n') ) { if ( isspace(*line) ) { line++; continue; } *flds++ = line; i++; while( (isspace(*line) == 0) && (*line != '\0') ) line++; if (isspace(*line)) *line++ = '\0'; } return(i); } /* Behaves almost like the Lattice dfind function, but dfindOne will not * keep a lock. */ int dfindOne(info, name, attr) struct FILEINFO *info; char *name; int attr; { BPTR lock; struct FILEINFO *tmpInfo; int retVal; if(!(lock = Lock(name, ACCESS_READ))) return(-1); tmpInfo = (struct FILEINFO *) AllocMem(sizeof(*tmpInfo), MEMF_CLEAR); if(retVal = Examine(lock, tmpInfo)) movmem((char *) tmpInfo, (char *) info, sizeof(*tmpInfo)); FreeMem((char *) tmpInfo, sizeof(*tmpInfo)); UnLock(lock); if(retVal && (attr || info->fib_DirEntryType < 0)) return(0); else return(-1); } SHAR_EOF if test 2757 -ne "`wc -c lib.c`" then echo shar: error transmitting lib.c '(should have been 2757 characters)' fi echo shar: extracting lmail.c '(10108 characters)' cat << \SHAR_EOF > lmail.c /* lmail.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 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, jack, jill@xyz.uucp ... ... ... 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. 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" */ #include #include #include "host.h" char *_TZ = "GMT0"; FILE *FOPEN(); #define FORWARD "Forward to" static FILE *mailfile; static FILE *tempfile; static char buf[BUFSIZ]; static char miscBuf[100]; static char *inFileName; static long int sequence = 0; static long tloc; static char chartime[40]; /* current time in characters */ static char *thetime; static char tfilename[100]; extern char mfilename[]; static char mailsent[100]; static char remotes[BUFSIZ]; static char *uucp = "uucp"; char *fgets(); int fputs(); extern int debuglevel; static char Subject[132] = ""; extern long DOSBase; static char *mcurdir; static char s_mcurdir[128]; /* current directory path (save malloc call) */ char * getcwd(); int chdir(); lmail(argc, argv, inname) int argc; char **argv; char *inname; { int argcount; char **argvec; int i; char timeBuf[40]; if (debuglevel > 5) { fprintf(stderr,"pcmail: argc %d ", argc); argcount = argc; argvec = argv; while (argcount--) fprintf(stderr," \"%s\"", *argvec++); fprintf(stderr,"\n"); time(&tloc); thetime = ctime(&tloc); sprintf(timeBuf,"%.3s, %.2s %.3s %.2s %.8s %s\n", thetime, thetime + 8, thetime + 4, thetime + 22, thetime + 11, timeZone); thetime = timeBuf; fprintf(stderr,"thetime: %s",thetime); } mcurdir = getcwd(s_mcurdir, sizeof(s_mcurdir)); chdir(spooldir); /* get sequence number */ mkfilename(tfilename, confdir, SFILENAME); if (debuglevel > 4) fprintf(stderr,"pcmail: opening %s\n", tfilename); if(tempfile = FOPEN(tfilename,"r", 't')) { 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); if(tempfile = FOPEN(tfilename,"w", 't')) { fprintf(tempfile,"%ld\n", (sequence+1)%10000); fclose(tempfile); } if(!(inFileName = inname)) { sprintf(miscBuf, TFILENAME, sequence); mkfilename(tfilename, tempdir, miscBuf); inFileName = tfilename; if (debuglevel > 5) fprintf(stderr,"pcmail: opening %s\n", inFileName); if (!(tempfile = FOPEN(inFileName,"w", 'b'))) { fprintf(stderr,"pcmail: can't open %s\n", inFileName); exit(1); } /* copy stdin to tempfile */ while (i = fread(buf, 1, sizeof(buf), stdin)) { fwrite(buf, i, 1, tempfile); } /* mail compiled with Lattice crashes if we use the following. Why? */ /* buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while (fgets(buf, sizeof(buf) - 2, stdin)) { if(buf[0]) fputs(buf, tempfile); } */ } else { if (!(tempfile = FOPEN(inFileName,"a", 'b'))) { fprintf(stdout,"pcmail: can't open %s\n",inFileName); return(0); } } /* append signature */ mkfilename(mfilename, home, SIGFILE); if (debuglevel > 4) fprintf(stderr,"pcmail: opening sigfile %s\n", mfilename); if(mailfile = FOPEN(mfilename,"r", 't')) { fputs("\n---\n", tempfile); buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while (fgets(buf, sizeof(buf) - 2, mailfile)) { if(buf[0]) fputs(buf, tempfile); } fclose(mailfile); } fclose(tempfile); /* loop on args, copying to appropriate postbox, * do remote only once * remote checking is done empirically, could be better */ remotes[0] = 0; if (!strcmp(argv[1],"-s")) { argv += 2; argc -= 2; if (argc <= 0) return(-1); strcpy(Subject, *argv); } argcount = argc; argvec = argv; while (--argcount > 0) { argvec++; if (debuglevel > 5) fprintf(stderr,"pcmail: arg# %d %s\n", argcount, *argvec); if (strchr(*argvec, '!') || strchr(*argvec, '@') || strchr(*argvec, '%')) { if (debuglevel > 5) fprintf(stderr,"pcmail: send to remote\n"); /* can we cram one more address on line */ if((strlen(remotes) + strlen(*argvec) + 3) > sizeof(remotes)) { /* 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 (remotes[0]) sendone(argc, argv, remotes, TRUE); /* mkfilename(mailsent, home, COPYFILE); if (debuglevel > 4) fprintf(stderr,"pcmail: copfile = %s\n", mailsent); sendone(argc, argv, mailsent, FALSE); */ unlink(tfilename); chdir(mcurdir); return(0); } /* 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) int argc; char **argv; char *address; int remote; { 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 */ struct FILEINFO info; if (remote) { /* sprintf all required file names */ sprintf(tmfilename,"%c.%.7s%04d", 'C', mailserv, sequence); importpath(icfilename, tmfilename); sprintf(tmfilename,"%c.%.7s%04d", 'D', mailserv, sequence); importpath(idfilename, tmfilename); sprintf(tmfilename,"%c.%.7s%04d", 'D', nodename, sequence); importpath(ixfilename, tmfilename); sprintf(rdfilename,"%c.%.7s%04d", 'D', nodename, sequence); sprintf(rxfilename,"%c.%.7s%04d", 'X', nodename, sequence); } else { /* postbox file name */ if (!strchr(address, SEPCHAR)) 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 (!dfindOne(&info, idfilename, 0) && info.fib_Size > 10 && (mailfile = FOPEN(idfilename,"r", 'b'))) { cp = fgets(buf, sizeof(buf), 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'))) { fprintf(stdout,"pcmail: cannot append to %s\n", idfilename); return(0); } if (debuglevel > 5) fprintf(stderr,"pcmail: append to mailfile\n"); time(&tloc); thetime = ctime(&tloc); sprintf(chartime,"%.3s, %.2s %.3s %.2s %.8s %s", thetime, thetime + 8, thetime + 4, thetime + 22, thetime + 11, timeZone); thetime = chartime; /* and work with our own copy */ fprintf(mailfile,"From %s %s", mailbox, thetime); if (remote) fprintf(mailfile," remote from %s", nodename); fputc('\n', mailfile); fprintf(mailfile,"Received: by %s (pcmail) %s\n", domain, thetime); fprintf(mailfile,"Date: %s\n", thetime); /* add Date:, From: and Message-ID: headers */ fprintf(mailfile,"From: %s <%s@%s>\n", name, mailbox, domain); fprintf(mailfile,"Message-ID: <%ld@%s>\n", sequence, domain); /* add To: headers */ fprintf(mailfile,"To: %s", *++argv); argc--; while (--argc > 0) fprintf(mailfile,", %s", *++argv); fputc('\n', mailfile); if (strlen(Subject)) fprintf(mailfile,"Subject: %s\n", Subject); fputc('\n', mailfile); /* copy spoolfile to postbox file */ if (debuglevel > 4) fprintf(stderr,"pcmail: copy spoolfile %s to %s\n", inFileName, idfilename); if (!(tempfile = FOPEN(inFileName,"r", 'b'))) { fprintf(stdout,"pcmail: can't open %s\n", inFileName); return(0); } buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while (fgets(buf, sizeof(buf) - 2, tempfile)) { if (!strncmp(buf,"From ", 5)) fputc('>', mailfile); if(buf[0]) fputs(buf, 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 */ if(!(mailfile = FOPEN(ixfilename,"w", 'b'))) { fprintf(stdout,"pcmail: cannot open %s\n", ixfilename); return(0); } fprintf(mailfile,"U %s %s\n", uucp, nodename); fprintf(mailfile,"F %s\n", rdfilename); fprintf(mailfile,"I %s\n", rdfilename); fprintf(mailfile,"C rmail %s\n", address); fclose(mailfile); /* create local C copy file */ if(!(mailfile = FOPEN(icfilename,"w", 't'))) { fprintf(stdout,"pcmail: cannot open %s\n", icfilename); return(0); } fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", idfilename, rdfilename, uucp, idfilename, uucp); fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", ixfilename, rxfilename, uucp, ixfilename, uucp); fclose(mailfile); } return(1); } SHAR_EOF if test 10108 -ne "`wc -c lmail.c`" then echo shar: error transmitting lmail.c '(should have been 10108 characters)' fi echo shar: extracting mail.c '(12248 characters)' cat << \SHAR_EOF > mail.c /* * mail.c */ /* The users refers to the letters with a number between 1 and numberOfLetters, * message 1 being the most recent. * * The messages are refered to internally with a number between 0 and * numberOfLetters - 1, with message numberOfLetters - 1 being the most recent. */ #include #include #include "host.h" #define VERSION "1.4 Camelot" FILE *FOPEN(); FILE *freopen(); /* int debuglevel = 1; */ #define LSIZE 256 #define SHORTLSIZE 132 static char line[LSIZE]; static char resp[LSIZE]; char mfilename[SHORTLSIZE]; struct ldesc { int delete; /* status of this message */ long adr; /* address of From line */ long date; /* address of Date: line */ long subject; /* address of Subject: line */ long from; /* address of From: line */ long size; /* number of lines */ struct ldesc *suc; /* link to previous letter */ struct ldesc *prev; /* link to next letter */ }; static struct ldesc *newLetter(struct ldesc *); static struct ldesc *letterN(int); static struct ldesc letterHead; static struct ldesc *curLetter = NULL; static int numberOfLetters = 0; static char thefilename[128]; static char tmailbox[64]; static char tmailbag[64]; static FILE *fmailbox; static FILE *rmailbox; static FILE *fmailbag; static int error = 0; static int printonly; static int PageCount = 0; mailmain(argc, argv) char **argv; { /* HOSTINIT; loadenv(); */ letterHead.prev = letterHead.suc = &letterHead; letterHead.adr = 0; mkfilename( tmailbox, tempdir, "mailbox"); mkfilename( tmailbag, tempdir, "mailbag"); unlink( tmailbox ); if ( mailbox == (char *)NULL ) mailbox = "???"; if (argc > 1 && !strncmp(argv[1],"-d", 2)) { debuglevel = atoi(argv[1] + 2); argc--; argv++; } if ( argc == 1 || ( argv[1][0] == '-' ) && ( argv[1][1] != 's' )) showmail(argc, argv ); else lmail(argc, argv, NULL ); finis(); } finis() { if ( fmailbag != (FILE *)NULL) fclose( fmailbag ); unlink( tmailbox ); unlink( tmailbag ); return( error ); } /* sendmail send message n to "line" Todo: we should supply a Subject line with the -s switch. */ sendmail( n, line ) { char *argv[50]; int argc; /* open a temporary file */ fmailbag = FOPEN( tmailbag, "w", 'b' ); copymsg(n, fmailbag, FALSE); fclose( fmailbag ); argc = getargs( line, argv ); lmail( argc, argv, tmailbag ); /* get rid of mailbag */ unlink( tmailbag ); } static userToInternal( i ) { return( numberOfLetters - i ); } static internalToUser( i ) { return( numberOfLetters - i ); } showmail(argc, argv) char **argv; { int i, j; char *p; long nextadr; struct ldesc *letter; struct FILEINFO info; /* get mailbox file name */ mkfilename( mfilename, maildir, mailbox ); /* parse arg's */ for (; argc > 1 && argv[1][0] == '-'; argv++, argc--) { switch(argv[1][1]) { case 'f': if ( argc >= 3) { if ( argv[2][0] == '=' ) mkfilename( mfilename, maildir, &argv[2][1] ); else strcpy( mfilename, argv[2] ); argv++; argc--; } else { fprintf(stderr,"Usage: mail -f filename\n"); finis(); } break; case 'p': printonly++; break; default: fprintf(stderr, "mail: unknown option %c\n", argv[1][1]); finis(); } } /* open real mailbox file */ if (dfindOne(&info, mfilename, 0) || !info.fib_Size) { fprintf( stdout, "No mail in %s.\n", mfilename ); return; } if (!(rmailbox = FOPEN( mfilename, "r", 'b' ))) { fprintf(stdout,"Unable to open %s.\n", mfilename); return; } /* open up tmp mailbox file */ if (( fmailbox = FOPEN( tmailbox, "w", 'b' )) == (FILE *)NULL ) { fprintf( stderr, "mail: cannot open %s for writing\n", tmailbox ); finis(); } /* copy real mailbox file to tmp mailbox file */ numberOfLetters = 0 ; nextadr = 0; line[sizeof(line) - 2] = '\n'; line[sizeof(line) - 1] = 0; while ( fgets(line, sizeof(line) - 2, rmailbox ) != (char *)NULL) { if(line[0]) fputs( line, fmailbox ); if ( strncmp( line, "From ", 5 ) == SAME ) { letter = newLetter(NULL); letter->from = letter->subject = letter->date = -1L; letter->adr = nextadr; letter->delete = FALSE; letter->size = 0L; }else if ( strncmp( line, "Date: ", 6 ) == SAME ) letter->date = nextadr; else if ( strncmp( line, "From: ", 6 ) == SAME ) letter->from = nextadr; else if ( strncmp( line, "Subject: ", 9 ) == SAME ) letter->subject = nextadr; letter->size += 1L; nextadr += strlen( line ); } letter->suc->adr = nextadr; /* close mailbox files */ fclose( rmailbox ); fclose( fmailbox ); fmailbox = FOPEN( tmailbox, "r", 'b' ); if ( printonly ) { j = numberOfLetters; while ( j > 0 ) pager( --j ); return; } printsub( -1 ); resp[sizeof(resp) - 2] = '\n'; resp[sizeof(resp) - 1] = 0; j = 1; while ( TRUE ) { j = min(numberOfLetters, max(1, j)); fprintf( stdout, "%d ? ", j ); if ( fgets( resp, sizeof(resp) - 2, stdin) == (char *)NULL ) break; switch ( resp[0] ) { default: fprintf(stderr, "mail %s: usage\n", VERSION); case '?': fprintf( stderr, "q\tquit\n" ); fprintf( stderr, "x\texit\tmailbox restored\n" ); fprintf( stderr, "p\tprint message\n" ); fprintf( stderr, "s [file] save message to a file (default =mbox)\n" ); fprintf( stderr, "w [file] save message to a file (default =mbox) without header\n" ); fprintf( stderr, "-^\tprint previous message\n" ); fprintf( stderr, "d\tdelete current message\n" ); fprintf( stderr, "u\tundelete current message\n" ); fprintf( stderr, "+n\tprint next message\n" ); fprintf( stderr, "h\tprint headers\n" ); fprintf( stderr, "H\tprint current header\n" ); fprintf( stderr, "f user\tforward current message to user\n" ); fprintf( stderr, "m user\tmail a message to user\n" ); fprintf( stderr, "[g] num\tset current message\n" ); break; case '+': case 'n': if(++j <= numberOfLetters) pager( userToInternal(j) ); break; case 'g': j = atoi( resp+2 ); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': j = atoi( resp ); break; case 'x': if(j > 0) { for(i = 0; i < numberOfLetters; i++) letterN(i)->delete = FALSE; } case 'q': goto donep; case '\n': case 'p': if(j > 0) pager( userToInternal(j) ); break; case '^': case '-': if(--j > 0) pager( userToInternal(j) ); break; case 'y': case 'w': case 's': if(j < 1) break; if (strlen(resp) <= 2) { strcpy(resp + 1," =mbox"); } if (resp[1] != ' ' || !(p = strtok(resp + 1," \t\n"))) { fprintf(stderr, "bad filename\n"); continue; } if ( *p == '=' && strlen(p) > 1) mkfilename( thefilename, maildir, p + 1 ); else strcpy( thefilename, p ); fprintf(stderr,"Appending to %s\n", thefilename ); if (!(fmailbag = FOPEN(thefilename, "a", 't'))) { fprintf( stderr, "mail: cannot append to %s\n", thefilename ); continue; } copymsg( userToInternal(j), fmailbag, resp[0]=='w' ); fclose( fmailbag ); letterN(userToInternal(j))->delete = TRUE; j++; break; case 'm': fprintf( stderr,"mail command not implemented yet.\n" ); break; case 'f': if(j < 1) break; if (resp[1] != ' ') { printf( "invalid command\n" ); continue; } sendmail( userToInternal(j), resp ); break; case 'd': if(j < 1) break; letterN(userToInternal(j))->delete = TRUE; j++; if (resp[1] == 'q') goto donep; break; case 'u': if(j < 1) break; letterN(userToInternal(j))->delete = FALSE; j++; if (resp[1] == 'q') goto donep; break; case 'h': printsub( -1 ); break; case 'H': if(j > 0) printsub( userToInternal(j) ); break; } } donep: for(i = 0; i < numberOfLetters; i++) if(letterN(i)->delete) { copyback(); break; } } readaline( adr, line ) long adr; char *line; { char buf[LSIZE]; char *cp; buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; *line = '\0'; if ( adr != -1L && !fseek( fmailbox, adr, 0 ) && fgets( buf, sizeof(buf) - 2, fmailbox )) strcpy( line, buf ); if ((cp = index( line, '\n' ))) *cp = '\0'; } /* returnaddress() { readaline( lp->from, line ); if ( ( i = index( line, '<' )) != 0 && ( k = index( line, '>')) != 0 && ( k > i ) ) { k -= i; strncpy( from, line[i], k ); from[k] = '\0'; } else { } } */ printsub( internalIndex ) int internalIndex; { struct ldesc *ld; int j; char from[LSIZE], subject[LSIZE], date[SHORTLSIZE], line[LSIZE]; int k, mink, maxk; pagereset(); if ( internalIndex == -1 ) { maxk = numberOfLetters -1; mink = 0; } else maxk = mink = internalIndex; for ( k = maxk ; k >= mink ; k-- ) { j = internalToUser( k ); ld = letterN(k); (void)strcpy(from, "unknown"); /* default to "unknown" */ readaline( ld->from, line ); if ( strlen( line ) > 5 ) { /* Assume From: mailbox@site.domain */ /* get first usable stuff after From: */ strcpy(from, line + 5); } /* Date: Wed May 13 23:59:53 1987 */ *date = '\0'; /* default date to null */ readaline( ld->date, date ); if ( strlen( date ) > 5 ) { sscanf( date + 5, "%*s %s %s", line, subject ); sprintf( date, "%s %s", line, subject ); } strcpy( subject, "--- no subject ---" ); readaline( ld->subject, line ); if ( strlen( line ) > 8 ) { strcpy( subject, line + 8); } date[6] = '\0'; sprintf( line, "%c%3d %6s (%6d) %s\n %s\n", ld->delete ? 'D' : ' ', j, date, ld->size, from, subject ); if ( pageline( line ) == TRUE ) break; } } copyback() { register i; if (!(fmailbag = FOPEN( mfilename, "w", 'b' ))) { fprintf (stderr, "mail: can't rewrite %s\n", thefilename ); finis(); } for ( i = 0; i < numberOfLetters; i++ ) if ( letterN(i)->delete == FALSE ) { copymsg( i, fmailbag, FALSE ); } fclose (fmailbag ); } /* copy a message if noheaders true, don't copy header lines */ copymsg( n, f, noheaders ) FILE *f; { long bytes; char buf[BUFSIZ]; struct ldesc *ld; ld = letterN(n); fseek( fmailbox, ld->adr, 0 ); bytes = ld->suc->adr - ld->adr; buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while ( noheaders && bytes > 0 && fgets( buf, sizeof(buf) - 2, fmailbox )) { bytes -= strlen( buf ); if ( strcmp( buf, "\n") == SAME ) { noheaders = FALSE; fputs( buf, f ); } } bytes = ld->suc->adr - ftell(fmailbox); while(bytes > 0 && fread(buf, min(bytes, sizeof(buf)), 1, fmailbox) == 1) { if(fwrite(buf, min(bytes, sizeof(buf)), 1, f) != 1) { fprintf(stderr,"write failed\n"); return; } bytes -= min(bytes, sizeof(buf)); } } pager(n) { long bytes; char buf[LSIZE]; struct ldesc *ld; ld = letterN(n); fseek( fmailbox, ld->adr, 0 ); bytes = ld->suc->adr - ld->adr; pagereset(); buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while ( bytes > 0 && fgets( buf, sizeof(buf) - 2, fmailbox )) { bytes -= strlen( buf ); if ( buf[0] && pageline( buf ) == TRUE ) break; } pageline( "\n" ); } pagereset() { PageCount = 0; } pageline( s ) char * s; { char c; fputs( s, stdout ); if ( ++PageCount > pagesize ) { PageCount = 0; fflush(stdout); c = get_one(); switch( c ) { case 'q': case 'Q': case '\003': case 'x': case 'X': return( TRUE ); } } return( FALSE ); } /* Allocate and insert a new ldesc after previous */ static struct ldesc *newLetter(previous) register struct ldesc *previous; { register struct ldesc *tmpldesc; if(!(tmpldesc = (struct ldesc *) calloc(1, sizeof(*tmpldesc)))) { fprintf(stderr,"Out of memory\n"); exit(1); } if(!previous) { previous = letterHead.prev; } tmpldesc->prev = previous; tmpldesc->suc = previous->suc; previous->suc->prev = tmpldesc; previous->suc = tmpldesc; numberOfLetters++; return(tmpldesc); } /* return reference to letter n */ static struct ldesc *letterN(n) int n; { register struct ldesc *lp = letterHead.suc; if(n < 0 || n >= numberOfLetters) { fprintf(stderr,"letterN: letter %n does not exist\n"); } while(n--) lp = lp->suc; return(lp); } SHAR_EOF if test 12248 -ne "`wc -c mail.c`" then echo shar: error transmitting mail.c '(should have been 12248 characters)' fi echo shar: extracting mailhost.c '(1160 characters)' cat << \SHAR_EOF > mailhost.c /* mailhost.c */ #include #include #include "host.h" static char *curdir; char * getcwd(); int chdir(); int debuglevel = 0; /* debuginglevel */ jmp_buf dcpexit; main( argc, argv ) int argc; char *argv[]; { int returnCode = 0; char curdirBuf[100]; /* Amiga specific prolog */ loadenv(); curdir = getcwd( curdirBuf, sizeof(curdirBuf) ); /* setup longjmp for error exit's */ if ( setjmp( dcpexit ) == 0 ) { mailmain( argc, argv ); } /* Amiga specific epilog */ exitenv(); chdir( curdir ); exit( returnCode ); } /* canonical name conversion routines importpath canonical -> host exportpath host -> canonical host your local pathname format canonical unix style */ importpath( host, canon ) char * host; char * canon; { extern char *pubdir; *host = '\0'; if ( *canon == '~' ) { if ( canon[1] == '/' ) strcpy( host, pubdir ); else { strcpy( host, home ); strcat( host, "/" ); } } strcat( host, canon ); if ( *host == '/' ) *host = ':'; } exportpath( canon, host ) char * host; char * canon; { strcpy( canon, host ); if ( *canon == ':' ) *canon = '/'; } SHAR_EOF if test 1160 -ne "`wc -c mailhost.c`" then echo shar: error transmitting mailhost.c '(should have been 1160 characters)' fi echo shar: extracting mlib.c '(591 characters)' cat << \SHAR_EOF > mlib.c /* lib.c Amiga library Things to do in uu host serial I/O directory stuff opendir, readdir, closedir prolog and epilog system call */ #include #include "host.h" #ifdef MANX #include int get_one() { char c; struct sgttyb stty, sttyo; ioctl( 0, TIOCGETP, &stty ); sttyo = stty; stty.sg_flags |= RAW; /* stty.sg_flags &= ~ ECHO; */ ioctl( 0, TIOCSETP, &stty ); c = fgetc( stdin ); ioctl( 0, TIOCSETP, &sttyo ); return( c ); } #else int get_one() { int c; raw(stdin); c = fgetc(stdin); cooked(stdin); return( c ); } #endif SHAR_EOF if test 591 -ne "`wc -c mlib.c`" then echo shar: error transmitting mlib.c '(should have been 591 characters)' fi echo shar: extracting ndir.c '(2157 characters)' cat << \SHAR_EOF > ndir.c #include "ndir.h" #include #ifdef MANX #include #endif #ifdef TEST #include #endif /* * support for Berkeley directory reading routine on a V7 file system */ extern char *malloc(); /* * open a directory. */ DIR * opendir(name) char *name; { register DIR *dirp; struct Lock *lock; #ifdef TEST fprintf( stderr, "opendir: Opening \"%s\"\n", name ); #endif if ( ( lock = Lock( name, ACCESS_READ )) == NULL ) { #ifdef TEST fprintf( stderr, "opendir: Can't open.\n" ); #endif return NULL; } if ( (dirp = (DIR *)malloc(sizeof(DIR))) == NULL ) { #ifdef TEST fprintf( stderr, "opendir: couldn't malloc %d\n",sizeof(DIR)); #endif UnLock( lock ); return NULL; } if ( !Examine( lock, &dirp->fib) ) { #ifdef TEST fprintf( stderr, "opendir: Couldn't Examine directory\n" ); #endif free( dirp ); UnLock( lock ); } dirp->lock = lock; #ifdef TEST fprintf( stderr, "opendir: Sucessful\n" ); #endif return dirp; } /* * get next entry in a directory. */ struct direct * readdir(dirp) register DIR *dirp; { static struct direct dir; while ( ExNext( dirp->lock, &dirp->fib ) ) { if ( dirp->fib.fib_DirEntryType <= 0 ) { dir.d_ino = 0; strcpy( dir.d_name, dirp->fib.fib_FileName ); #ifdef TEST fprintf( stderr, "readdir: OK \"%s\"\n", dir.d_name); #endif dir.d_namlen = strlen(dir.d_name); dir.d_reclen = DIRSIZ(&dir); return (&dir); } } #ifdef TEST fprintf( stderr, "readdir: No More Entries.\n" ); #endif strcpy( dir.d_name, "" ); return NULL; } /* * close a directory. */ void closedir(dirp) register DIR *dirp; { UnLock( dirp->lock ); free((char *)dirp); } #ifdef TEST #ifdef MANX #include #endif main() { char command[100]; struct DIR *dirp; struct direct *dp; while(gets(command) != NULL) { fprintf( stderr, "test: %s\n", command ); if ((dirp = opendir( command )) == NULL ) { fprintf( stderr, "couldn't open dir %s\n", command ); } else { while ((dp = readdir(dirp)) != NULL) fprintf( stderr, "%s", dp->d_name ); closedir( dirp ); } } } #endif SHAR_EOF if test 2157 -ne "`wc -c ndir.c`" then echo shar: error transmitting ndir.c '(should have been 2157 characters)' fi echo shar: extracting ndir.h '(1242 characters)' cat << \SHAR_EOF > ndir.h /* @(#)ndir.h 1.4 4/16/85 */ #include #ifndef MANX #include #endif #ifndef DEV_BSIZE #define DEV_BSIZE 512 #endif #define DIRBLKSIZ DEV_BSIZE #define MAXNAMLEN 255 struct direct { long d_ino; /* inode number of entry */ short d_reclen; /* length of this record */ short d_namlen; /* length of string in d_name */ char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ }; /* * The DIRSIZ macro gives the minimum record length which will hold * the directory entry. This requires the amount of space in struct direct * without the d_name field, plus enough space for the name with a terminating * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. */ #ifdef DIRSIZ #undef DIRSIZ #endif /* DIRSIZ */ #define DIRSIZ(dp) \ ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) /* * Definitions for library routines operating on directories. */ /* typedef struct _dirdesc { int dd_fd; long dd_loc; long dd_size; char dd_buf[DIRBLKSIZ]; } DIR; */ typedef struct _dirdesc { struct Lock *lock; struct FileInfoBlock fib; } DIR; #ifndef NULL #define NULL 0L #endif extern DIR *opendir(); extern struct direct *readdir(); extern void closedir(); SHAR_EOF if test 1242 -ne "`wc -c ndir.h`" then echo shar: error transmitting ndir.h '(should have been 1242 characters)' fi echo shar: extracting pccp.c '(13168 characters)' cat << \SHAR_EOF > pccp.c /* pccp - copy files between systems * * SYNOPSIS * pccp [-C] [-r] [-v] [-xd] fromfile... tofile * * DESCRIPTION * pccp is a partial implementation of the UNIX uucp command. The business * of pccp is to translate user level copy commands into command files * understood by uupc. pccp may also start uupc on these files. * * A file name may be a local pathname or of the form * system!pathname * where system is one of the sites listed in the uupc systems file. * If the remote pathname contains wild cards (? * and so on) these * will be expanded on the remote system. This program does no wildcard * expansion. The caller, the local uupc or the remote uupc have to decide * about wildcards. * * A pathname is one of the following: * a complete pathname * * a pathname preceded by ~user/. ~user will be expanded to * the home directory of the user on the appropriate system. * The name ~/ will be expanded to the public uucp directory. * * anything else will be prependded with the path of the current * directory. * * OPTIONS * -C Copy the outgoing files to the spool directory. This lets * you remove the source file without affecting the file transfer. * The default action is to transfer directly from the source * file. * * -r Do not start the transfer. Just queue the job. * * -v Verbose. Will at least display the version. * * -xd This option will be passed on to uupc. It specifies the * the debug level. d is a digit between zero and nine. */ /* The code for finding an executable is taken from the cc program written * by Fred Fish. There are restrictions on the use of that code. See * the cc program on Fish disk 28 for more info. * * As regards all other code in this program: use it any way you want, * I put no restrictions on it. * * 6-FEB-88 Johan Widen * USENET: jw@sics.se */ #include #include #include "host.h" #define VERSION "1.0 6-FEB-88" #define PROGRAM "pccp" /* * Set list of places to search for various executables, libraries, etc. * Searched in order, first match wins, null string is current directory. * Note that these names are used as prefixes exactly as given, so * device names must end in ':' and directory names must end in '/'. * */ static char *Devices[] = { "", "vd0:", "ram:", "df0:", NULL }; static char *BinDirs[] = { "", "c:", "df0:c/", NULL }; static void usage(); static void pathArgUsage(); static int checkLocalRemote(int, char**); static int sequenceNumber(int); static char **copyToSpool(int, char**, int); static void createCommandFile(int, char **, char**, int, int, int, char *); static void removeSpoolFiles(int, char**); static int expandFileName(char *, char *); static char *checkAlloc(int); static char *locate(char *, char **); static int readable(char *); static int runCommand(char *); int debuglevel = 0; main(argc, argv) int argc; char **argv; { int copyFlag = 0; int queueOnlyFlag = 0; int verboseFlag = 0; int localToRemote; char **pathArgs; int sequence; char remoteHost[80]; char executeBuf[80]; for(argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) { switch(argv[0][1]) { case 'C': copyFlag = 1; break; case 'r': queueOnlyFlag = 1; break; case 'v': verboseFlag = 1; break; case 'x': if(isdigit(argv[0][2])) debuglevel = argv[0][2] - '0'; else usage(); break; default: usage(); } } if(argc < 2) usage(); loadenv(); if(verboseFlag) fprintf(stderr,"%s\n", VERSION); if((localToRemote = checkLocalRemote(argc, argv)) < 0) exit(1); pathArgs = argv; if(localToRemote && copyFlag) { sequence = sequenceNumber(argc - 1); pathArgs = copyToSpool(argc, pathArgs, sequence); } else { sequence = sequenceNumber(1); } createCommandFile(argc, argv, pathArgs, sequence, localToRemote, copyFlag, remoteHost); if(queueOnlyFlag) exit(0); sprintf(executeBuf,"%s -r1 -s%s -x%d", locate("uupc", BinDirs), remoteHost, debuglevel); exit(runCommand(executeBuf)); } static void usage() { fprintf(stderr,"%s version %s\n", PROGRAM, VERSION); fprintf(stderr,"Usage: %s [-C] [-r] [-v] [-xd] fromfiles... tofile\n", PROGRAM); fprintf(stderr,"-C means copy to spool before sending.\n"); fprintf(stderr,"-r means queue only, do not start uupc.\n"); fprintf(stderr,"-v means verbose.\n"); fprintf(stderr,"-xd '0'<= d <= '9' set debug level for uupc.\n"); fprintf(stderr,"file may be a local pathname or system!pathname\n"); fprintf(stderr, "pathname may be a full path or begin with ~user (\"~/\" means public uucp\n"); fprintf(stderr, "directory). Other pathnames get prepended with current directory\n"); exit(1); } /* checkLocalRemote(argc, argv) * int argc; Number of pathnames. * char **argv; Pathnames. * * Description: we currently require that one of the following holds * 1. The last argument is a remote pathname. All other arguments are * local pathnames. * * 2. There are only two arguments. The first argument is a remote path- * name and the last argument is a local pathname. * * Return 1 if case 1 holds. Return 0 if case 2 holds. Otherwise return -1. */ static int checkLocalRemote(argc, argv) register int argc; register char **argv; { register int i; if(argc == 2 && strchr(argv[0],'!')) { if(strchr(argv[1],'!')) { pathArgUsage(); return(-1); } return(0); } /* first argument is a local pathname */ if(!strchr(argv[argc - 1],'!')) { pathArgUsage(); return(-1); } for(i = 1; i < argc - 1; i++) if(strchr(argv[i],'!')) { pathArgUsage(); return(-1); } return(1); } static void pathArgUsage() { fprintf(stderr,"%s: pathname arguments must be either:\n", PROGRAM); fprintf(stderr,"\tremote!path localpath\n or\n"); fprintf(stderr,"\tlocalpath... remote!path\n"); } /* int sequenceNumber(inc) * int inc; Reserve this many numbers; * * Description: The filenames in the spool area are made unique by including * a sequence number in them. Get the next sequence number. Update the sequence * number. */ static int sequenceNumber(inc) int inc; { char sequencePath[256]; FILE *sequenceFile; int sequence; mkfilename(sequencePath, confdir, SFILENAME); if(sequenceFile = fopen(sequencePath,"r")) { fscanf(sequenceFile,"%ld", &sequence); fclose(sequenceFile); } else sequence = 0; if(!(sequenceFile = fopen(sequencePath,"w"))) { fprintf(stderr,"%s: unable to create %s\n", PROGRAM, sequencePath); exit(3); } fprintf(sequenceFile,"%04d\n", (sequence + inc)%10000); fclose(sequenceFile); return(sequence); } /* char **copyToSpool(argc, oldPathArgs, sequence) * int argc; Number of pathnames. * char **oldPathArgs; Files to copy to spool area. * int sequence; File name sequence number. * * Description: copy the first argc - 1 files to the spool area. The spool * files are given unique names. The new names are returned together with * the original last argument. */ static char ** copyToSpool(argc, oldPathArgs, sequence) int argc; register char **oldPathArgs; int sequence; { register char **newPathArgs; char spoolName[256]; char dFileName[80]; char buf[BUFSIZ]; register int i; int bytesRead; FILE *inFile, *outFile; newPathArgs = (char **) checkAlloc(argc*sizeof(char **)); newPathArgs[argc - 1] = oldPathArgs[argc - 1]; for(i = 0; i < argc - 1; i++) { sprintf(dFileName,"D.%.7s%04d", nodename, sequence++); mkfilename(spoolName, spooldir, dFileName); newPathArgs[i] = checkAlloc(strlen(spoolName) + 1); strcpy(newPathArgs[i], spoolName); } for(i = 0; i < argc - 1; i++) { if(!expandFileName(oldPathArgs[i], spoolName)) { removeSpoolFiles(i, newPathArgs); exit(4); } if(!(inFile = fopen(spoolName,"r"))) { fprintf(stderr,"%s: unable to open %s\n", PROGRAM, spoolName); removeSpoolFiles(i, newPathArgs); exit(5); } if(!(outFile = fopen(newPathArgs[i],"w"))) { fprintf(stderr,"%s: unable to open %s\n", PROGRAM, newPathArgs[i]); removeSpoolFiles(i, newPathArgs); exit(6); } while (bytesRead = fread(buf, 1, sizeof(buf), inFile)) { if(fwrite(buf, bytesRead, 1, outFile) != 1) { fclose(outFile); fprintf(stderr,"%s: write error when copying %s to %s\n", PROGRAM, spoolName, newPathArgs[i]); removeSpoolFiles(i + 1, newPathArgs); exit(7); } } fclose(inFile); fclose(outFile); } return(newPathArgs); } static void createCommandFile(argc, oldPathArgs, pathArgs, sequence, localToRemote, copyFlag, remoteHost) int argc; char **oldPathArgs; char **pathArgs; int sequence; int localToRemote; int copyFlag; char *remoteHost; { char buf[BUFSIZ]; char expandedPath[256]; char cFilePath[256]; char cFileName[80]; FILE *cFile; char *cp, *remoteFile; register int i; int spoolDirLen; int length; if(localToRemote) cp = pathArgs[argc - 1]; else cp = pathArgs[0]; remoteFile = strchr(cp,'!') + 1; strncpy(remoteHost, cp, remoteFile - cp - 1); remoteHost[remoteFile - cp - 1] = 0; sprintf(cFileName,"C.%.7s%04d", remoteHost, sequence); mkfilename(cFilePath, spooldir, cFileName); if(!(cFile = fopen(cFilePath,"w"))) { fprintf(stderr,"%s: unable to open %s\n", PROGRAM, cFilePath); if(localToRemote && copyFlag) removeSpoolFiles(argc - 1, pathArgs); exit(8); } spoolDirLen = strlen(spooldir); if(localToRemote) { for(i = 0; i < argc - 1; i++) { if(!expandFileName(oldPathArgs[i], expandedPath)) { fclose(cFile); unlink(cFilePath); exit(8); } if(copyFlag) { sprintf(buf,"S %s %s uucp - %s 0666\n", expandedPath, remoteFile, pathArgs[i] + spoolDirLen + 1); } else { sprintf(buf,"S %s %s uucp - %s 0666\n", expandedPath, remoteFile, expandedPath); } /* The first arg should really be the original file but uupc */ /* does not handle this yet. */ length = strlen(buf); if(1 != fwrite(buf, length, 1, cFile)) { fprintf(stderr,"%s: write error on %s\n", PROGRAM, cFilePath); if(copyFlag) removeSpoolFiles(argc - 1, pathArgs); fclose(cFile); unlink(cFilePath); exit(9); } } } else { if(!expandFileName(pathArgs[1], expandedPath)) { fclose(cFile); unlink(cFilePath); exit(10); } sprintf(buf,"R %s %s uucp\n", remoteFile, expandedPath); length = strlen(buf); if(1 != fwrite(buf, length, 1, cFile)) { fprintf(stderr,"%s: write error on %s\n", PROGRAM, cFilePath); fclose(cFile); unlink(cFilePath); exit(11); } } fclose(cFile); } static void removeSpoolFiles(count, newPathArgs) int count; register char **newPathArgs; { register int i; for(i = 0; i < count; i++) { unlink(newPathArgs[i]); } } static int expandFileName(from, to) register char *from; register char *to; { char *cp; char user[50]; if(from[0] == '/' || from[0] == ':') { strcpy(to, from); to[0] = ':'; } else if(from[0] == '~') { if(!(cp = strchr(from,'/'))) { strcat(from, "/"); cp = strchr(from,'/'); } if((cp - from) > 1) { strncpy(user, from + 1, cp - from - 1); user[cp - from - 1] = 0; if(strcmp(user, mailbox)) { fprintf(stderr,"%s: unknown user %s\n", PROGRAM, user); return(0); } mkfilename(to, home, cp + 1); } else { mkfilename(to, pubdir, cp + 1); } } else { getcwd(to, 256); cp = to + strlen(to) - 1; if(*cp != '/' && *cp != ':') { strcpy(cp + 1, "/"); } strcat(cp, from); } return(1); } static char * checkAlloc(size) int size; { char *cp; if(!(cp = malloc(size))) { fprintf(stderr,"%s: out of memory\n", PROGRAM); exit(2); } return(cp); } /* * Look through the list of paths pointed to by "vec" until we find * a file with name given pointed to by "namep". If none is found, * the name pointed to by namep is returned. */ static char *locate(namep, vec) char *namep; char **vec; { static char namebuf[64]; while (*vec != NULL) { sprintf(namebuf, "%s%s", *vec, namep); if (readable(namebuf)) { namep = namebuf; break; } vec++; } return(namep); } /* * Check to see if the file exists and is readable. */ static int readable(name) char *name; { register int status = 0; register int fildes; fildes = Lock(name, ACCESS_READ); if (fildes != 0) { UnLock (fildes); status = 1; } return(status); } static int runCommand(command) char *command; { int status; register char *cp; char *prog, *args; struct ProcID child; /* This code assumes that there is at least one argument */ prog = cp = command; while(*cp && *cp != ' ') cp++; *cp++ = 0; while(*cp == ' ') cp++; args = cp; if(forkl(prog, prog, args, NULL, NULL, &child) == -1) { fprintf(stderr,"%s: unable to execute %s\n", PROGRAM, prog); status = 1; } else { status = wait(&child); } return(status); } SHAR_EOF if test 13168 -ne "`wc -c pccp.c`" then echo shar: error transmitting pccp.c '(should have been 13168 characters)' fi # End of shell archive exit 0