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