home *** CD-ROM | disk | FTP | other *** search
- /*
- * U U M A I L
- * This program when invoked in the form:
- * uumail host!user will consult the local usemap for
- * the proper routing.
- *
- * If it finds it, it will invoke the proper uux call
- * to send the mail.
- * Otherwise it aborts with an error 68 (host unknown)
- ***************************************************************************
- This work in its current form is Copyright 1986 Stan Barber
- with the exception of opath, gethostname and the original getpath which
- as far as I know are in the Public Domain. This software may be distributed
- freely as long as no profit is made from such distribution and this notice
- is reproducted in whole.
- ***************************************************************************
- This software is provided on an "as is" basis with no guarantee of
- usefulness or correctness of operation for any purpose, intended or
- otherwise. The author is in no way liable for this software's performance
- or any damage it may cause to any data of any kind anywhere.
- ***************************************************************************
- * $Log: uumail.c,v $
- * Revision 3.0 86/03/14 12:05:00 sob
- * Release of 3/15/86 --- 3rd Release
- *
- * Revision 2.20 86/03/14 11:57:46 sob
- *
- *
- * Revision 2.19 86/03/11 11:29:11 sob
- * Added Copyright Notice
- *
- * Revision 2.18 86/03/04 18:20:40 sob
- * Fixed some problems with local vs. non-local mail.
- *
- * Revision 2.17 86/02/26 03:06:47 sob
- * Added error checking for a null name.
- *
- * Revision 2.16 86/02/23 23:49:40 sob
- *
- *
- * Revision 2.15 86/02/23 23:19:09 sob
- * This version will hopefully work with the new pipeoutput option from
- * aliasing.
- * Stan
- *
- * Revision 2.14 86/02/18 02:56:38 sob
- * Correct pointer problem with linked list.
- * Stan
- *
- * Revision 2.13 86/02/17 18:43:37 sob
- * Updated with linked list for addresses. This will allow aliasing which
- * will be added next.
- * Stan
- *
- * Revision 2.12 86/02/17 17:33:12 sob
- * This update incorporates changes to the command line flags to
- * conform more with the syntax of sendmail.
- * Stan
- *
- * Revision 2.11 86/02/07 16:06:16 sob
- * Altered the code to always unlink the temporary letter file when
- * DEBUG is NOT defined.
- * Stan
- *
- * Revision 2.10 85/12/26 16:50:23 sob
- * Added fixes to allow uupath myhostname to work correctly.
- * Stan
- *
- * Revision 2.9 85/12/10 20:36:01 sob
- * Added new return flag from getpath EX_TEMPFAIL to signal that the
- * path database is currently being updated.
- *
- * Revision 2.8 85/12/02 16:51:39 sob
- * Added a fix to cope with percents in addresses returned by opath.
- * Thank to steve@umd-cs.UUCP for the bug report.
- *
- * Revision 2.7 85/11/18 12:36:48 sob
- * Added the -h option to cause uumail NOT to add a From_ line.
- *
- * Revision 2.6 85/11/14 20:20:06 sob
- * Added #ifdef DEBUG to allow compiliation with out DEBUG installed
- *
- * Revision 2.5 85/11/14 20:14:11 sob
- * Another little buggie in the log format...sheesh.
- *
- * Revision 2.4 85/11/13 15:53:18 sob
- * Reformated the log file a little bit.
- *
- * Revision 2.3 85/11/08 03:03:51 sob
- * This is the release version.
- *
- *
- * Revision 2.2 85/09/30 02:51:18 sob
- * This version uses opath when defined during compile time.
- * With a bit of cleaning up, this is a release version.
- *
- * Revision 2.1 85/09/30 02:46:06 sob
- * *** empty log message ***
- *
- * Revision 2.0 85/09/09 18:22:56 UUCP
- * *** empty log message ***
- *
- * Revision 2.0 85/09/09 18:22:56 UUCP
- * Added flags to conform with sendmail. Also updated the flags it could send
- * to uux to conform with 4.3 uux command.
- * Will add name resolution and header checking.
- * Also will allow multiple addresses per line.
- *
- * Revision 1.7 85/08/03 00:49:14 UUCP
- * Cleaned up with lint.
- * Stan Barber
- *
- * Revision 1.6 85/07/11 19:30:00 sob
- * changed PATHSIZE to PATHSIZ to conform with uupath
- *
- * Revision 1.5 85/07/11 18:08:13 sob
- * This one works both as uumail and uupath!
- * Stan
- *
- * Revision 1.4 85/07/10 18:35:05 sob
- * moved DBM to getpath
- * Stan Barber
- *
- * Revision 1.3 85/07/09 01:28:14 sob
- * First attempt to integrate uupath
- * Not successful. Changed PATHALIAS define
- * to DBM... will ultimately alter getpath as well
- * added gethostname call to fill in for local host.
- *
- * Revision 1.2 85/07/08 05:29:16 sob
- * This one works with pathalias database...
- * need to modify to substitue for uupath.
- * Stan
- *
- * Revision 1.1 85/07/08 03:11:10 sob
- * Initial revision
- *
- */
- #define _DEFINE
-
- #include "uuconf.h"
-
-
- EXTERN bool uupath;
- extern int errno;
- extern struct passwd *getpwuid();
- extern FILE *popen();
- extern char *ctime();
- extern char *getlogin();
- extern char *index();
- extern char *rindex();
- extern char *malloc();
- extern char *getenv();
- extern char *Alias();
- EXTERN char progname[12];
- EXTERN char *paths;
- char templet[64];
- char * from;
- struct mailname addrlist; /* list of addresses */
- int local;
- static char Version[] ="$Header: uumail.c,v 3.0 86/03/14 12:05:00 sob RELEASE_3 $";
-
- main(argc, argv)
- char **argv;
- {
- FILE *out, *tmpf; /* output to uux, temp file */
- char lbuf[512]; /* for pipe to uux */
- char sender[512]; /* accumulated path of sender */
- char sys[64]; /* a system in path */
- char cmd[2000];
- char **av;
- int i,
- error = 0,
- bangcnt, hopcount = 30;
-
- char c,
- grade = 'C',
- name[20], /* The system name (if any) */
- *fname,
- *path, /* uupath to the system */
- *sysname, /* points to the system name */
- *p, *q, *r, /* tmp pointer to argv's */
- *rsys,
- *FullName;
- bool GrabTo,safecf,NoAlias,startuux,noheader,metoo;
- extern intsig();
- struct mailname *lp;
-
- if (signal(SIGINT, SIG_IGN) != SIG_IGN)
- (void) signal(SIGINT, intsig);
- if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
- (void) signal(SIGHUP, intsig);
- (void) signal(SIGTERM, intsig);
- (void) signal(SIGPIPE, SIG_IGN);
- /* initialize Boolean Values */
- startuux = safecf = TRUE;
- metoo=GrabTo=NoAlias=noheader = FALSE;
-
- for (i = 3; i < 20; i++)
- (void) close(i);
- errno = 0;
- gethostname(Myname,32);
- paths=DATABASE;
- logfile=LOGFILE;
- argv[argc] = NULL;
- av = argv;
- p = rindex(*av, '/');
- if (p++ == NULL)
- p = *av;
- strcpy(progname ,p);
- if(strcmp(p,"uupath") == 0)
- uupath = TRUE;
- while ((p = *++av) != NULL && p[0] == '-')
- {
- switch (p[1])
- {
-
- case 'C': /* select configuration file */
- ConfFile = &p[2];
- safecf = FALSE;
-
- break;
-
- case 'g': /* set grade */
- grade = p[2];
- break;
-
- # ifdef DEBUG
- case 'd': /* debug */
- Debug= atoi(&p[2]);
- if (Debug == 0) Debug = 1;
- setbuf(stdout, (char *) NULL);
- printf("Version %s\n", Version);
- break;
- # endif DEBUG
-
- case 'f': /* from address */
- case 'r': /* obsolete -f flag */
- p += 2;
- if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
- {
- p = *++av;
- if (p == NULL || *p == '-')
- {
- syserr("No \"from\" person");
- av--;
- break;
- }
- }
- if (from != NULL)
- {
- syserr("More than one \"from\" person");
- break;
- }
- from = p;
- break;
-
- case 'w': /* just print the path */
- uupath = TRUE;
- break;
- case 'h': /* don't add a From line */
- noheader = TRUE;
- break;
- case 'n': /* don't alias any addresses */
- NoAlias = TRUE;
- break;
- case 't': /* read Header for addresses */
- GrabTo = TRUE;
- break;
- case 'o': /* sendmail-like options flag */
- switch(p[2]){
- case 'm': /* send this message to the sender*/
- metoo=TRUE;
- break;
- case 'c': /* don't connect to expensive
- mailer, or don't start uux*/
- startuux = FALSE;
- break;
- }
- break;
- }
-
- }
-
- if(*av==NULL && GrabTo!= TRUE)
- {
- fprintf(stderr,"Usage: %s [flags] address\n",progname);
- exit(EX_USAGE);
- }
-
- if (ConfFile == NULL) ConfFile = CONFIGFILE;
-
- if (AliasFile == NULL) AliasFile = ALIASFILE;
-
- /* get login name of the sender... use environment variables if possible */
-
- if(from==NULL || strlen(from) == 0){
- if (((from = getenv("LOGNAME")) == NULL) || (strlen(from) == 0))
- from = getenv("USER");
- if ((from == NULL) || (strlen(from) == 0))
- from = getlogin();
- if ((from == NULL) || (strlen(from) == 0))
- from = getpwuid(geteuid())->pw_name;
- }
-
- /* If this is not uupath, then there must be a letter */
-
- if (!uupath)
- {
- #ifdef DEBUG
- if (Debug) printf("Mail from %s\n",from);
- #endif
- /*
- * Make temporary file for letter
- * (I wish ACCESS(2) would take care of this better !!)
- */
- if ((p=getenv("HOME"))== NULL)
- p="/tmp";
- sprintf(&templet[0],"%s/.uumXXXXXX",p);
- mktemp(templet);
- unlink(templet);
- if ((i=open(templet,2)) < 0)
- {
- p="/tmp";
-
- sprintf(&templet[0],"%s/.uumXXXXXX",p);
- mktemp(templet);
- unlink(templet);
- }
- else
- {
- close(i);
- unlink(templet);
- }
- #ifdef DEBUG
- if (Debug>2) printf("Temp file is %s\n",templet);
- #endif
- if((tmpf = fopen(templet, "w")) == NULL){
- fprintf(stderr, "%s : can't open %s for writing\n", progname,templet);
- fclose(stdin);
- exit(EX_CANTCREAT);
-
- }
- while(fgets(lbuf,sizeof lbuf,stdin))
- fputs(lbuf,tmpf);
- fclose(tmpf);
- fclose(stdin);
- /* file now saved */
- if((tmpf = fopen(templet, "r")) == NULL){
- fprintf(stderr, "%s : can't open %s for reading\n", progname,templet);
- exit(EX_OSERR);
- }
-
- }
- (void) strcpy(sender, "");
-
- path = malloc(PATHSIZ);
-
- /* build address list */
-
-
- while (*av != NULL && *av != NULL)
- add(*av++,&addrlist);
-
- if(metoo) add(from,&addrlist); /* add me to the list too */
-
- if(!NoAlias) alias(); /* do aliasing if not turned off */
- #ifndef NOALIAS /* process forwarding files */
- for (lp = addrlist.m_next;lp;lp = lp->m_next) forward(lp->m_name);
- #endif
-
- for (lp = addrlist.m_next;lp;lp = lp->m_next) /* mail it out */
- {
-
- if(strlen(lp->m_name) == 0) continue;
-
- local = bangcnt = 0;
-
- q = p = lp->m_name;
-
- sysname = &name[0];
-
- /* this is uupath command */
- if (uupath)
-
- {
- (void) strcpy(sysname ,p);
- #ifdef OPATH
- if ((error = getpath (&name[0], path,paths)) != EX_OK)
- {
- if (error == EX_NOHOST) fprintf (stderr, "System %s not found in network map\n", &name[0]);
- if (error == EX_NOINPUT) fprintf(stderr,"Database %s could not be opened\n",paths);
- if (error == EX_TEMPFAIL) fprintf(stderr,"Database %s is being updated\nTry again later.\n",paths);
- exit(EX_NOHOST);
- }
- if (strcmp(path,"%s") == 0) local = 1;
- }
- else
- {
- /* check for pipe to another program output here */
- if (lp->m_pipe == TRUE){
- strcat(cmd,lp->m_name);
- goto pipeout;
- }
- #ifdef RFC976
- if (index(p,'@') == NULL) strcpy(path,oupath(p));
- else strcpy(path,opath(p));
-
- #else
- if (index(p,'!') != NULL) strcpy(path,oupath(p));
- else strcpy(path,opath(p));
- #endif
-
- /* fix string to allow % to be untranslated by printf and
- * friends
- */
- if ((r=index(path,'%')) != NULL)
- {
- char t[PATHSIZ];
- strncpy(t,path,(r-path));
- strcat(t,"%");
- strcat(t,r);
- path = &t[0];
- #ifdef DEBUG
- if (Debug>3)
- fprintf(stderr,"In percent fix, %s\n",t);
- #endif
- }
-
-
-
-
- #ifdef DEBUG
- if (Debug >1) fprintf(stderr,"Opath returns %s\n",path);
- #endif
-
- if (path[0] == '!') /* no match in pathalias database */
- {
- deadletter(tmpf,local);
- unlink(templet);
- exit(EX_NOHOST);
- }
-
- if (strcmp(path,p) == 0 && index(path,'!') == NULL )
- {
- strcpy(path,Myname);
- local = 1;
- }
- } /* end of else uupath */
- #else
- }
- else
- {
- /* check and pipe to output if here */
- do /* count bangs */
- {
- while (((c = *p++) != '!') && (c != '\0'));
- if (c == '!') bangcnt++;
- }
- while (c != '\0' && bangcnt == 1);
- ;
- if (bangcnt >= 1) /* expand path */
- {
- while ((*sysname++ = *q++) != '!');
- *--sysname = '\0';
-
- }
- /* insert code here to look at uucp neighbors & local host */
- }
- if (bangcnt == 0) {
- strcpy(sysname,Myname);
- local = 1;
- }
- #ifdef DEBUG
- if (Debug>1) printf("sysname = %s\n",&name[0]);
- #endif
-
- if (local == 0 && (error = getpath (&name[0], path,paths)) != EX_OK)
- {
- if (error == EX_NOHOST) fprintf (stderr, "System %s not found in network map\n", &name[0]);
- if (error == EX_NOINPUT) fprintf(stderr,"Database %s could not be opened\n",paths);
- if (error == EX_TEMPFAIL) fprintf(stderr,"Database %s is being updated\nTry again later.\n",paths);
- exit(EX_NOHOST);
- }
-
- if (local!=0) path = "%s";
- if (strcmp (path,"%s") == 0) local = 1;
- #endif
-
-
- #ifdef DEBUG
- if(Debug>1) printf("Path = %s\n",path);
- #endif
-
- p = q; /* save name */
- for (i = 0; i < 1 && *p != '\0'; p++)
- if (*p == '/')
- i++;
- fname = &sender[0];
-
- if (uupath)
- sprintf(fname,path,"username");
- else
- sprintf(fname,path,q);
-
- p = fname;
- #ifdef DEBUG
- if (Debug> 4) printf("p = %s local = %d\n ",p,local);
- #endif
- rsys = &sys[0];
-
- if (local == 0)
- {
- while((*rsys++ = *p++) != '!');
- *--rsys = '\0';
- }
- else
- /* local host, remove @ sign */
- {
- strcpy(rsys,lp->m_name);
- q=rsys;
- if (index(rsys,'@') != NULL)
- {
- while (*q++ !='@');
- *--q='\0';
- }
- /* assume that if it has a bang in it uux
- will either reject it or know what to do with it */
- /* this is a little gross */
- if ((q = index(rsys,'!')) != NULL)
- {
- local=0;
- strcpy(&sys[0],rsys);
- sys[q-rsys]='\0';
- p=q+1;
- }
- }
-
- if ((local==0 && *fname =='\0') || (local!=0 && &sys[0]=='\0')) {
- fprintf(stdout, "null name\n");
- exit(EX_DATAERR);
- }
- #ifdef DEBUG
- if (Debug>3)
- printf("p = %s sys = %s fname = %s\n",p, &sys[0],fname);
- #endif
-
- if (uupath)
- {
- printf ("Path to %s: %s\n", lp->m_name, fname);
- continue;
- }
- else
- {
- if (local!= 0)
- sprintf(cmd, LOCALMAIL, &sys[0]);
- else {
- sprintf(cmd,"%s - ",REALUUX);
- if (!startuux)
- strcat(cmd,"-r");
- #ifndef NORETURN
- if (from)
- {
- strcat(cmd," -a");
- strcat(cmd,from);
- }
- #endif
- #ifndef NOGRADE
- if (grade)
- {
- char work[10];
- sprintf(work," -g%c",grade);
- strcat(cmd,work);
- }
- #endif
- if (index(p, '!'))
- {
- char work[100];
- sprintf(work, " %s!rmail \\(%s\\)", &sys[0], p);
- strcat(cmd,work);
- }
- else
- {
- char work[100];
- sprintf(work, " %s!rmail %s", &sys[0], p);
- strcat(cmd,work);
- }
- }
- pipeout:
- #ifdef DEBUG
- if (Debug) fprintf(stderr,"Command is %s\n",cmd);
- #endif
- rewind(tmpf);
- #ifdef DEBUG
- if (Debug)
- out = fopen("UUMAIL.TEST","w");
- else
- #endif
- out = popen(cmd, "w");
- /* fputs(lbuf, out); */
- if (!noheader) Putfrom(tmpf,out);
- while (fgets(lbuf, sizeof lbuf, tmpf))
- fputs(lbuf, out);
-
- /* may not be needed */
- if (local!=0)
- fprintf(out,"\n.\n");
-
- #ifdef DEBUG
- if (Debug)
- i = fclose(out);
- else
- #endif
- i = pclose(out);
- if ((i & 0377) != 0)
- {
- fprintf(stderr, "pclose: status 0%o\n", i);
- deadletter(tmpf,local);
- #ifdef DEBUG
- if (Debug <3)
- #endif
- unlink(templet);
- exit(EX_OSERR);
- }
- #ifdef LOG
- maillog(cmd);
- #endif
- }
- }
- #ifdef DEBUG
- if (Debug <3)
- #endif
- unlink(templet);
- exit(EX_OK);
- }
-
- /* print an error message on stderr */
-
- syserr(string)
- char * string;
- {
- fprintf(stderr,"%s\n",string);
- }
-
- /* make a unix type From line and send it out the stream */
-
- Putfrom(into,outto)
- FILE *into, *outto;
- {
- char *asctime();
- struct tm *bp, *localtime();
- char *tp, *zp;
- int n,fromflag=0;
- char buf[128];
- long iop;
-
- /*
- * Format time
- */
- time(&iop);
- bp = localtime(&iop);
- tp = asctime(bp);
- /* zp = tzname[bp->tm_isdst];*/
- /* sprintf(buf, "%s%s %.16s %.3s %.5s", from, tp, zp, tp+20);*/
- sprintf(buf, "From %s %.16s %.4s", from, tp, tp+20);
-
- #ifdef UGLYUUCP
- if (local == 0){
- strcat(buf," remote from ");
- strcat(buf,Myname);
- }
- #endif
- strcat(buf,"\n");
- write(outto->_file,buf,strlen(buf));
- fflush(outto);
-
- if (fgets(buf,sizeof(buf),into) != NULL)
- if((strncmp(&buf[0], "From ", 5) == 0 || strncmp(&buf[0], "From:", 5) == 0))
- write(outto->_file,">",1);
-
- write(outto->_file,buf,strlen(buf));
- }
-
-
- /* attempt to return dead letter */
- /* we'll do better on this one next time */
-
- deadletter(retlet, here)
- FILE *retlet;
- int here;
- {
- if(getlogin() != NULL) syserr("Letter failed....\n");
- }
-
- /* go here on a signal we want to catch */
- intsig()
- {
- unlink(templet);
- exit(EX_OK);
- }
-
- /* put command strings in the logfile */
-
- #ifdef LOG
-
- maillog(command)
- char * command;
- {
- FILE *f;
- char atime[24];
- long clock;
- time (&clock);
- strncpy(atime,ctime(&clock),24);
-
- if ((f=fopen(logfile,"a")) != NULL)
- {
- fprintf(f,"%s: %s - %s\n",progname,atime,command);
- fclose(f);
- }
- }
-
- #endif
-
-