home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume3 / uumail2 / uumail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  12.5 KB  |  619 lines

  1. /*
  2.  *  U U M A I L
  3.  *  This program when invoked in the form:
  4.  *  uumail host!user will consult the local usemap for
  5.  *  the proper routing.
  6.  * 
  7.  *  If it finds it, it will invoke the proper uux call
  8.  *  to send the mail.
  9.  *  Otherwise it aborts with an error 68 (host unknown)
  10.  * $Log:    uumail.c,v $
  11.  * Revision 2.9  85/12/10  20:36:01  sob
  12.  * Added new return flag from getpath EX_TEMPFAIL to signal that the
  13.  * path database is currently being updated.
  14.  * 
  15.  * Revision 2.8  85/12/02  16:51:39  sob
  16.  * Added a fix to cope with percents in addresses returned by opath.
  17.  * Thank to steve@umd-cs.UUCP for the bug report.
  18.  * 
  19.  * Revision 2.7  85/11/18  12:36:48  sob
  20.  * Added the -h option to cause uumail NOT to add a From_ line.
  21.  * 
  22.  * Revision 2.6  85/11/14  20:20:06  sob
  23.  * Added #ifdef DEBUG to allow compiliation with out DEBUG installed
  24.  * 
  25.  * Revision 2.5  85/11/14  20:14:11  sob
  26.  * Another little buggie in the log format...sheesh.
  27.  * 
  28.  * Revision 2.4  85/11/13  15:53:18  sob
  29.  * Reformated the log file a little bit.
  30.  * 
  31.  * Revision 2.3  85/11/08  03:03:51  sob
  32.  * This is the release version.
  33.  * 
  34.  * 
  35.  * Revision 2.2  85/09/30  02:51:18  sob
  36.  * This version uses opath when defined during compile time.
  37.  * With a bit of cleaning up, this is a release version.
  38.  * 
  39.  * Revision 2.1  85/09/30  02:46:06  sob
  40.  * *** empty log message ***
  41.  * 
  42.  * Revision 2.0  85/09/09  18:22:56  UUCP
  43.  * *** empty log message ***
  44.  * 
  45.  * Revision 2.0  85/09/09  18:22:56  UUCP
  46.  * Added flags to conform with sendmail. Also updated the flags it could send
  47.  * to uux to conform with 4.3 uux command.
  48.  * Will add name resolution and header checking.
  49.  * Also will allow multiple addresses per line.
  50.  * 
  51.  * Revision 1.7  85/08/03  00:49:14  UUCP
  52.  * Cleaned up with lint.
  53.  * Stan Barber
  54.  * 
  55.  * Revision 1.6  85/07/11  19:30:00  sob
  56.  * changed PATHSIZE to PATHSIZ to conform with uupath
  57.  * 
  58.  * Revision 1.5  85/07/11  18:08:13  sob
  59.  * This one works both as uumail and uupath!
  60.  * Stan
  61.  * 
  62.  * Revision 1.4  85/07/10  18:35:05  sob
  63.  * moved DBM to getpath
  64.  * Stan Barber
  65.  * 
  66.  * Revision 1.3  85/07/09  01:28:14  sob
  67.  * First attempt to integrate uupath
  68.  * Not successful. Changed PATHALIAS define
  69.  * to DBM... will ultimately alter getpath as well
  70.  * added gethostname call to fill in for local host.
  71.  * 
  72.  * Revision 1.2  85/07/08  05:29:16  sob
  73.  * This one works with pathalias database...
  74.  * need to modify to substitue for uupath.
  75.  * Stan
  76.  * 
  77.  * Revision 1.1  85/07/08  03:11:10  sob
  78.  * Initial revision
  79.  * 
  80.  */
  81. #define _DEFINE
  82.  
  83. #include "uuconf.h"
  84.  
  85.  
  86. EXTERN bool uupath;
  87. extern int      errno;
  88. extern struct passwd *getpwuid();
  89. extern FILE    *popen();
  90. extern char     *ctime();
  91. extern char    *getlogin();
  92. extern char    *index();
  93. extern char    *rindex();
  94. extern char    *malloc();
  95. extern char     *getenv();
  96. EXTERN char    progname[12];
  97. EXTERN char  *paths;
  98. int local;
  99. char templet[64];
  100. char * from;
  101.  
  102.  
  103. static char Version[] ="$Header: uumail.c,v 2.9 85/12/10 20:36:01 sob Exp $";
  104.  
  105. main(argc, argv)
  106.     char **argv;
  107. {
  108.     FILE *out, *tmpf;    /* output to uux, temp file */
  109.     char lbuf[512]; /* for pipe to uux */
  110.     char sender[512];    /* accumulated path of sender */
  111.     char sys[64];    /* a system in path */
  112.     char cmd[2000];
  113.     char **av;
  114.     int i,
  115.             error = 0,
  116.             bangcnt, hopcount = 30,
  117.         metoo=0, noheader = 0,
  118.         startuux ;
  119.         
  120.     char    c,
  121.             grade = 'C',
  122.        name[20],             /* The system name (if any) */
  123.        *fname,
  124.        *path,            /* uupath to the system */
  125.            *sysname,            /* points to the system name */
  126.            *p, *q, *r,            /* tmp pointer to argv's */
  127.        *rsys,
  128.        *FullName;
  129.        bool GrabTo,safecf,NoAlias;
  130.        extern intsig();
  131.  
  132.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  133.         (void) signal(SIGINT, intsig);
  134.     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  135.         (void) signal(SIGHUP, intsig);
  136.     (void) signal(SIGTERM, intsig);
  137.     (void) signal(SIGPIPE, SIG_IGN);
  138.  
  139.  
  140.     for (i = 3; i < 20; i++)
  141.         (void) close(i);
  142.     errno = 0;
  143.     gethostname(Myname,32);
  144.     paths=DATABASE;
  145.     logfile=LOGFILE;
  146.     argv[argc] = NULL;
  147.     av = argv;
  148.     p = rindex(*av, '/');
  149.     if (p++ == NULL)
  150.         p = *av;
  151.     strcpy(progname ,p);
  152.     if(strcmp(p,"uupath") == 0)
  153.         uupath = TRUE;
  154.     while ((p = *++av) != NULL && p[0] == '-')
  155.     {
  156.         switch (p[1])
  157.         {
  158.  
  159.           case 'C':    /* select configuration file */
  160.             ConfFile = &p[2];
  161.             safecf = FALSE;
  162.  
  163.             break;
  164.  
  165.           case 'g':   /* set grade */
  166.             grade = p[2];
  167.             break;
  168.     
  169. # ifdef DEBUG
  170.           case 'd':    /* debug */
  171.             Debug= atoi(&p[2]);
  172.             if (Debug == 0) Debug = 1;
  173.             setbuf(stdout, (char *) NULL);
  174.             printf("Version %s\n", Version);
  175.             break;
  176. # endif DEBUG
  177.  
  178.           case 'f':    /* from address */
  179.           case 'r':    /* obsolete -f flag */
  180.             p += 2;
  181.             if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
  182.             {
  183.                 p = *++av;
  184.                 if (p == NULL || *p == '-')
  185.                 {
  186.                     syserr("No \"from\" person");
  187.                     av--;
  188.                     break;
  189.                 }
  190.             }
  191.             if (from != NULL)
  192.             {
  193.                 syserr("More than one \"from\" person");
  194.                 break;
  195.             }
  196.             from = p;
  197.             break;
  198.  
  199.           case 'w':    /* just print the path */
  200.             uupath = TRUE;
  201.             break;
  202.           case 'm':    /* send to me too */
  203.             metoo = TRUE;
  204.             break;
  205.           case 'c':    /* connect to non-local mailers */
  206.             startuux= TRUE;
  207.             break;
  208.           case 'h':    /* don't add a From line */
  209.             noheader = TRUE;
  210.             break;
  211.             }
  212.     
  213.         }
  214.  
  215.     if(*av==NULL && GrabTo!= TRUE)
  216.     {
  217.         fprintf(stderr,"Usage: %s [flags] address\n",progname);
  218.         exit(EX_USAGE);
  219.     }
  220.  
  221.     if (ConfFile == NULL) ConfFile = CONFIGFILE;
  222.  
  223.     if(from==NULL || strlen(from) == 0){
  224.         if (((from = getenv("LOGNAME")) == NULL) || (strlen(from) == 0))
  225.             from = getenv("USER");
  226.         if ((from == NULL) || (strlen(from) == 0))
  227.             from = getlogin();
  228.         if ((from == NULL) || (strlen(from) == 0))
  229.             from = getpwuid(geteuid())->pw_name;
  230.     }
  231.  
  232. if (!uupath)
  233. {    
  234. #ifdef DEBUG
  235.     if (Debug) printf("Mail from %s\n",from);
  236. #endif
  237.     /*
  238.      * Make temporary file for letter
  239.      * (I wish ACCESS(2) would take care of this better !!)
  240.      */
  241.     if ((p=getenv("HOME"))== NULL)
  242.         p="/tmp";
  243.     sprintf(&templet[0],"%s/.uumXXXXXX",p);
  244.     mktemp(templet);
  245.     unlink(templet);
  246.     if ((i=open(templet,2)) < 0)
  247.         {
  248.             p="/tmp";
  249.     
  250.             sprintf(&templet[0],"%s/.uumXXXXXX",p);
  251.             mktemp(templet);
  252.             unlink(templet);
  253.         }
  254.     else
  255.         {
  256.             close(i);
  257.             unlink(templet);
  258.         }
  259. #ifdef DEBUG
  260.     if (Debug>2) printf("Temp file is %s\n",templet);
  261. #endif
  262.     if((tmpf = fopen(templet, "w")) == NULL){
  263.         fprintf(stderr, "%s : can't open %s for writing\n", progname,templet);
  264.         fclose(stdin);
  265.         exit(EX_CANTCREAT);
  266.  
  267.         }
  268.     while(fgets(lbuf,sizeof lbuf,stdin))
  269.         fputs(lbuf,tmpf);
  270.     fclose(tmpf);
  271.     fclose(stdin);
  272. /* file now saved */
  273.     if((tmpf = fopen(templet, "r")) == NULL){
  274.         fprintf(stderr, "%s : can't open %s for reading\n", progname,templet);
  275.         exit(EX_OSERR);
  276.     }
  277.     
  278. }    
  279.     (void) strcpy(sender, "");
  280.  
  281.     path = malloc(PATHSIZ);
  282.  
  283.     av--;
  284.  
  285.     if(metoo)
  286.     {
  287.     *av = from;
  288.     av --;
  289.     }
  290.     
  291.     while (av++ != NULL && *av != NULL)
  292.     {
  293.     local = bangcnt = 0;
  294.     
  295.     
  296.     q = p = *av;
  297.     
  298.     sysname = &name[0];
  299.  
  300.     
  301.     if (uupath) 
  302.  
  303.     {
  304.     (void) strcpy(sysname ,p);
  305. #ifdef OPATH
  306.     if ((error = getpath (&name[0], path,paths)) != EX_OK)
  307.         {
  308.         if (error == EX_NOHOST) fprintf (stderr, "System %s not found in network map\n", &name[0]);
  309.         if (error == EX_NOINPUT) fprintf(stderr,"Database %s could not be opened\n",paths);
  310.         if (error == EX_TEMPFAIL) fprintf(stderr,"Database %s is being updated\nTry again later.\n",paths);
  311.         exit(EX_NOHOST);
  312.         }
  313.     }
  314.     else 
  315.     if (index(p,'@') == NULL) strcpy(path,oupath(p)); 
  316.         else strcpy(path,opath(p));
  317.  
  318. /* fix string to allow % to be untranslated by printf and 
  319.  * friends 
  320.  */
  321.    if ((r=index(path,'%')) != NULL)
  322.     {
  323.         char t[PATHSIZ];
  324.         strncpy(t,path,(r-path));
  325.         strcat(t,"%");
  326.         strcat(t,r);
  327.         path = &t[0];
  328. #ifdef DEBUG
  329.     if (Debug>3)
  330.         fprintf(stderr,"In percent fix, %s\n",t);
  331. #endif
  332.     }
  333.  
  334.  
  335.  
  336.  
  337. #ifdef DEBUG
  338.     if (Debug >1) fprintf(stderr,"Opath returns %s\n",path);
  339. #endif
  340.  
  341.     if (path[0] == '!')  /* no match in pathalias database */
  342.     {
  343.         deadletter(tmpf,local);
  344.         unlink(templet);
  345.         exit(EX_NOHOST);
  346.     }
  347.    
  348.    if (strcmp(path,p) == 0)
  349.     {
  350.     strcpy(path,Myname);
  351.     local = 1;
  352.     }
  353.  
  354. #else
  355.     }
  356.     else
  357. {
  358.     do                        /* count bangs */
  359.         {
  360.             while (((c = *p++) != '!') && (c != '\0'));
  361.                 if (c == '!') bangcnt++;
  362.         }
  363.     while (c != '\0' && bangcnt == 1);
  364.         ;
  365.     if (bangcnt >= 1)                /* expand path */
  366.         {
  367.             while ((*sysname++ = *q++) != '!');
  368.                 *--sysname = '\0';
  369.  
  370.             }
  371.     /* insert code here to look at uucp neighbors & local host */
  372.     if (bangcnt == 0) {
  373.             strcpy(sysname,Myname);
  374.             local = 1;
  375.             }
  376.     }
  377. #ifdef DEBUG
  378.     if (Debug>1) printf("sysname = %s\n",&name[0]);
  379. #endif
  380.     
  381.     if (!local && (error = getpath (&name[0], path,paths)) != EX_OK)
  382.         {
  383.         if (error == EX_NOHOST) fprintf (stderr, "System %s not found in network map\n", &name[0]);
  384.         if (error == EX_NOINPUT) fprintf(stderr,"Database %s could not be opened\n",paths);
  385.         if (error == EX_TEMPFAIL) fprintf(stderr,"Database %s is being updated\nTry again later.\n",paths);
  386.         exit(EX_NOHOST);
  387.         }
  388.  
  389.        if (local) path = sysname;
  390. #endif
  391.  
  392.  
  393. #ifdef DEBUG
  394.        if(Debug>1) printf("Path = %s\n",path);
  395. #endif
  396.  
  397.     p = q;                    /* save name */
  398.     for (i = 0; i < 1 && *p != '\0'; p++)
  399.         if (*p == '/')
  400.         i++;
  401.     fname = &sender[0];
  402.  
  403.         if (uupath)
  404.         sprintf(fname,path,"username");
  405.     else
  406.         sprintf(fname,path,q);
  407.  
  408.     p = &sender[0];
  409.     rsys = &sys[0];
  410.  
  411.     if (!local)
  412.         {
  413.         while((*rsys++ = *p++) != '!');
  414.         *--rsys = '\0';
  415.         }
  416.         else
  417. /* local host, remove @ sign */
  418.         {
  419.         strcpy(rsys,*av);
  420.         q=rsys;
  421.         if (index(rsys,'@') != 0)
  422.             { 
  423.                 while (*q++ !='@');
  424.                 *--q='\0';
  425.             }
  426.         /* assume that if it has a bang in it uux
  427.             will either reject it or know what to do with it */
  428.         /* this is a little gross */
  429.         if ((q = index(rsys,'!')) != 0)
  430.             {
  431.             local=0;
  432.             strcpy(&sys[0],rsys);
  433.             sys[q-rsys]='\0';
  434.             p=q+1;
  435.             }
  436.     }
  437.         
  438.     if ((!local && *fname =='\0') || (local && &sys[0]=='\0')) {
  439.         fprintf(stdout, "null name\n");
  440.         exit(EX_DATAERR);
  441.     }
  442. #ifdef DEBUG
  443.     if (Debug>3)
  444.         printf("p = %s sys = %s fname = %s\n",p, &sys[0],fname);
  445. #endif
  446.  
  447.     if (uupath)
  448.         {
  449.         printf ("Path to %s:  %s\n", *av, fname);
  450.         continue;
  451.         }
  452.     else
  453.     {
  454.         if (local)
  455.             sprintf(cmd, LOCALMAIL, &sys[0]);
  456.         else {
  457.             strcpy(cmd,"uux - ");
  458.         if (!startuux)
  459.             strcat(cmd,"-r");
  460. #ifndef NORETURN
  461.         if (from)
  462.             {
  463.             strcat(cmd," -a");
  464.             strcat(cmd,from);
  465.             }
  466. #endif
  467. #ifndef NOGRADE
  468.         if (grade)
  469.             {
  470.             char work[10];
  471.             sprintf(work," -g%c",grade);
  472.             strcat(cmd,work);
  473.             }
  474. #endif        
  475.         if (index(p, '!'))
  476.             {
  477.                 char work[100];
  478.                 sprintf(work, " %s!rmail \\(%s\\)",  &sys[0], p);
  479.                 strcat(cmd,work);
  480.             }
  481.         else
  482.             {
  483.                 char work[100];
  484.                 sprintf(work, " %s!rmail %s", &sys[0], p);
  485.                 strcat(cmd,work);
  486.             }
  487.         }
  488. #ifdef DEBUG
  489.     if (Debug) fprintf(stderr,"Command is %s\n",cmd);
  490. #endif
  491.         rewind(tmpf);
  492. #ifdef DEBUG
  493.         if (Debug)
  494.             out = fopen("UUMAIL.TEST","w");
  495.         else
  496. #endif
  497.             out = popen(cmd, "w");
  498. /*        fputs(lbuf, out); */
  499.         if (!noheader) Putfrom(tmpf,out);
  500.         while (fgets(lbuf, sizeof lbuf, tmpf))
  501.             fputs(lbuf, out);
  502.  
  503. /* may not be needed */
  504.         if (local)
  505.             fprintf(out,"\n.\n");
  506.  
  507. #ifdef DEBUG
  508.         if (Debug)
  509.             i = fclose(out);
  510.         else
  511. #endif
  512.             i = pclose(out);
  513.         if ((i & 0377) != 0)
  514.             {
  515.                 fprintf(stderr, "pclose: status 0%o\n", i);
  516.                 deadletter(tmpf,local);
  517. #ifdef DEBUG
  518.                 if (Debug <3) unlink(templet);
  519. #endif
  520.                 exit(EX_OSERR);
  521.             }
  522. #ifdef LOG
  523.         maillog(cmd);
  524. #endif
  525.        }
  526.     }
  527. #ifdef DEBUG
  528.     if (Debug <3) unlink(templet);
  529. #endif
  530. exit(EX_OK);
  531. }
  532.  
  533. /* print an error message on stderr */
  534.  
  535. syserr(string)
  536. char * string;
  537. {
  538.     fprintf(stderr,"%s\n",string);
  539. }
  540.  
  541. /* make a unix type From line and send it out the stream */
  542.  
  543. Putfrom(into,outto)
  544. FILE *into, *outto;
  545. {
  546.     char    *asctime();
  547.     struct    tm *bp, *localtime();
  548.     char    *tp, *zp;
  549.     int    n,fromflag=0;
  550.     char buf[128];
  551.     long iop;
  552.  
  553.     /*
  554.      * Format time
  555.      */
  556.     time(&iop);
  557.     bp = localtime(&iop);
  558.     tp = asctime(bp);
  559. /*    zp = tzname[bp->tm_isdst];*/
  560. /*    sprintf(buf, "%s%s %.16s %.3s %.5s", from, tp, zp, tp+20);*/
  561.     sprintf(buf, "From %s %.16s %.4s", from, tp, tp+20);
  562.  
  563. #ifdef UGLYUUCP
  564.     if (!local){
  565.             strcat(buf," remote from ");
  566.             strcat(buf,Myname);
  567.            }
  568. #endif
  569.     strcat(buf,"\n");
  570.     write(outto->_file,buf,strlen(buf));
  571.     fflush(outto);
  572.  
  573.     if (fgets(buf,sizeof(buf),into) != NULL)
  574.     if((strncmp(&buf[0], "From ", 5) == 0 || strncmp(&buf[0], "From:", 5) == 0))
  575.          write(outto->_file,">",1);
  576.     
  577.     write(outto->_file,buf,strlen(buf));
  578. }
  579.  
  580.  
  581. /* attempt to return dead letter */
  582. /* we'll do better on this one next time */
  583.  
  584. deadletter(retlet, here)
  585. FILE *retlet;
  586. int here;
  587. {
  588.     if(getlogin() != NULL) syserr("Letter failed....\n");
  589. }
  590.  
  591. /* go here on a signal we want to catch */
  592. intsig()
  593. {
  594.     unlink(templet);
  595.     exit(EX_OK);
  596. }
  597.  
  598. /* put command strings in the logfile */
  599.  
  600. #ifdef LOG
  601.  
  602. maillog(command)
  603. char * command;
  604. {
  605.     FILE *f;
  606.     char atime[24];
  607.     long clock;
  608.     time (&clock);
  609.     strncpy(atime,ctime(&clock),24);
  610.  
  611.     if ((f=fopen(logfile,"a")) != NULL)
  612.         {
  613.             fprintf(f,"%s: %s - %s\n",progname,atime,command);
  614.             fclose(f);
  615.         }
  616. }
  617.  
  618. #endif
  619.