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)
- * $Log: uumail.c,v $
- * 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 progname[12];
- EXTERN char *paths;
- int local;
- char templet[64];
- char * from;
-
-
- static char Version[] ="$Header: uumail.c,v 2.9 85/12/10 20:36:01 sob Exp $";
-
- 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,
- metoo=0, noheader = 0,
- startuux ;
-
- 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;
- extern intsig();
-
- 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);
-
-
- 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 'm': /* send to me too */
- metoo = TRUE;
- break;
- case 'c': /* connect to non-local mailers */
- startuux= TRUE;
- break;
- case 'h': /* don't add a From line */
- noheader = TRUE;
- break;
- }
-
- }
-
- if(*av==NULL && GrabTo!= TRUE)
- {
- fprintf(stderr,"Usage: %s [flags] address\n",progname);
- exit(EX_USAGE);
- }
-
- if (ConfFile == NULL) ConfFile = CONFIGFILE;
-
- 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 (!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);
-
- av--;
-
- if(metoo)
- {
- *av = from;
- av --;
- }
-
- while (av++ != NULL && *av != NULL)
- {
- local = bangcnt = 0;
-
-
- q = p = *av;
-
- sysname = &name[0];
-
-
- 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);
- }
- }
- else
- if (index(p,'@') == NULL) strcpy(path,oupath(p));
- else strcpy(path,opath(p));
-
- /* 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)
- {
- strcpy(path,Myname);
- local = 1;
- }
-
- #else
- }
- else
- {
- 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 && (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) path = sysname;
- #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 = &sender[0];
- rsys = &sys[0];
-
- if (!local)
- {
- while((*rsys++ = *p++) != '!');
- *--rsys = '\0';
- }
- else
- /* local host, remove @ sign */
- {
- strcpy(rsys,*av);
- q=rsys;
- if (index(rsys,'@') != 0)
- {
- 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,'!')) != 0)
- {
- local=0;
- strcpy(&sys[0],rsys);
- sys[q-rsys]='\0';
- p=q+1;
- }
- }
-
- if ((!local && *fname =='\0') || (local && &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", *av, fname);
- continue;
- }
- else
- {
- if (local)
- sprintf(cmd, LOCALMAIL, &sys[0]);
- else {
- strcpy(cmd,"uux - ");
- 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);
- }
- }
- #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)
- 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) unlink(templet);
- #endif
- exit(EX_OSERR);
- }
- #ifdef LOG
- maillog(cmd);
- #endif
- }
- }
- #ifdef DEBUG
- if (Debug <3) unlink(templet);
- #endif
- 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){
- 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
-