home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / Mail / send.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  5KB  |  303 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #
  3.  
  4. #include "rcv.h"
  5.  
  6. /*
  7.  * Mail -- a mail program
  8.  *
  9.  * Mail to others.
  10.  */
  11.  
  12. /*
  13.  * Send message described by the passed pointer to the
  14.  * passed output buffer.  Return -1 on error, but normally
  15.  * the number of lines written.
  16.  */
  17.  
  18. send(mailp, obuf)
  19.     struct message *mailp;
  20.     FILE *obuf;
  21. {
  22.     register struct message *mp;
  23.     register int t;
  24.     unsigned int c;
  25.     FILE *ibuf;
  26.     int lc;
  27.  
  28.     mp = mailp;
  29.     ibuf = setinput(mp);
  30.     c = msize(mp);
  31.     lc = 0;
  32.     while (c-- > 0) {
  33.         putc(t = getc(ibuf), obuf);
  34.         if (t == '\n')
  35.             lc++;
  36.         if (ferror(obuf))
  37.             return(-1);
  38.     }
  39.     return(lc);
  40. }
  41.  
  42. /*
  43.  * Interface between the argument list and the mail1 routine
  44.  * which does all the dirty work.
  45.  */
  46.  
  47. mail(people)
  48.     char **people;
  49. {
  50.     register char *cp2;
  51.     register int s;
  52.     char *buf, **ap;
  53.     struct header head;
  54.  
  55.     for (s = 0, ap = people; *ap != (char *) -1; ap++)
  56.         s += strlen(*ap) + 1;
  57.     buf = salloc(s+1);
  58.     cp2 = buf;
  59.     for (ap = people; *ap != (char *) -1; ap++) {
  60.         cp2 = copy(*ap, cp2);
  61.         *cp2++ = ' ';
  62.     }
  63.     if (cp2 != buf)
  64.         cp2--;
  65.     *cp2 = '\0';
  66.     head.h_to = buf;
  67.     head.h_subj = NOSTR;
  68.     head.h_cc = NOSTR;
  69.     head.h_seq = 0;
  70.     mail1(&head);
  71.     return(0);
  72. }
  73.  
  74.  
  75. /*
  76.  * Send mail to a bunch of user names.  The interface is through
  77.  * the mail routine below.
  78.  */
  79.  
  80. sendmail(str)
  81.     char *str;
  82. {
  83.     register char **ap;
  84.     char *bufp;
  85.     register int t;
  86.     struct header head;
  87.  
  88.     if (blankline(str))
  89.         head.h_to = NOSTR;
  90.     else
  91.         head.h_to = str;
  92.     head.h_subj = NOSTR;
  93.     head.h_cc = NOSTR;
  94.     head.h_seq = 0;
  95.     mail1(&head);
  96.     return(0);
  97. }
  98.  
  99. /*
  100.  * Mail a message on standard input to the people indicated
  101.  * in the passed header.  (Internal interface).
  102.  */
  103.  
  104. mail1(hp)
  105.     struct header *hp;
  106. {
  107.     register char *cp;
  108.     int pid, i, s;
  109.     char **namelist;
  110.     struct name *to;
  111.     FILE *mtf;
  112.  
  113.     /*
  114.      * Collect user's mail from standard input.
  115.      * Get the result as mtf.
  116.      */
  117.  
  118.     pid = -1;
  119.     if (hp->h_subj == NOSTR)
  120.         hp->h_seq = 0;
  121.     else
  122.         hp->h_seq = 1;
  123.     if ((mtf = collect(hp)) == NULL)
  124.         return(-1);
  125.     if (fsize(mtf) == 0 && hp->h_subj == NOSTR) {
  126.         printf("No message !?!\n");
  127.         goto out;
  128.     }
  129.     if (intty && value("askcc") != NOSTR)
  130.         grabh(hp, GCC);
  131.     else if (intty) {
  132.         printf("EOT\n");
  133.         flush();
  134.     }
  135.  
  136.     /*
  137.      * Now, take the user names from the combined
  138.      * to and cc lists and do all the alias
  139.      * processing.
  140.      */
  141.  
  142.     senderr = 0;
  143.     to = usermap(cat(extract(hp->h_to), extract(hp->h_cc)));
  144.     if (to == NIL) {
  145.         printf("No recipients specified\n");
  146.         goto topdog;
  147.     }
  148.  
  149.     /*
  150.      * Look through the recipient list for names with /'s
  151.      * in them which we write to as files directly.
  152.      */
  153.  
  154.     to = outof(to, mtf, hp);
  155.     to = verify(to);
  156.     if (senderr) {
  157. topdog:
  158.         unlink(deadletter);
  159.         exwrite(deadletter, mtf, 1);
  160.     }
  161.     if (to == NIL)
  162.         goto out;
  163.     to = elide(to);
  164.     mechk(to);
  165.     if (count(to) > 1)
  166.         hp->h_seq++;
  167.     if (hp->h_seq > 0)
  168.         if ((mtf = infix(hp, mtf)) == NULL) {
  169.             fprintf(stderr, ". . . message lost, sorry.\n");
  170.             return(-1);
  171.         }
  172.     namelist = unpack(to);
  173.     if (value("record") != NOSTR)
  174.         savemail(value("record"), hp, mtf, namelist);
  175.  
  176.     /*
  177.      * Wait, to absorb a potential zombie, then
  178.      * fork, set up the temporary mail file as standard
  179.      * input for "mail" and exec with the user list we generated
  180.      * far above. Return the process id to caller in case he
  181.      * wants to await the completion of mail.
  182.      */
  183.  
  184.     wait(&s);
  185.     rewind(mtf);
  186.     pid = fork();
  187.     if (pid == -1) {
  188.         perror("fork");
  189.         goto out;
  190.     }
  191.     if (pid == 0) {
  192.         for (i = 1; i  < 17; i++)
  193.             signal(i, SIG_IGN);
  194.         s = fileno(mtf);
  195.         for (i = 3; i < 15; i++)
  196.             if (i != s)
  197.                 close(i);
  198.         close(0);
  199.         dup(s);
  200.         close(s);
  201.         execv(MAIL, namelist);
  202.         perror(MAIL);
  203.         exit(1);
  204.     }
  205.  
  206. out:
  207.     fclose(mtf);
  208.     return(pid);
  209. }
  210.  
  211. /*
  212.  * Prepend a header in front of the collected stuff
  213.  * and return the new file.
  214.  */
  215.  
  216. FILE *
  217. infix(hp, fi)
  218.     struct header *hp;
  219.     FILE *fi;
  220. {
  221.     extern char tempMail[];
  222.     register FILE *nfo, *nfi;
  223.     register int c;
  224.  
  225.     if ((nfo = fopen(tempMail, "w")) == NULL) {
  226.         perror(tempMail);
  227.         return(fi);
  228.     }
  229.     if ((nfi = fopen(tempMail, "r")) == NULL) {
  230.         perror(tempMail);
  231.         fclose(nfo);
  232.         return(fi);
  233.     }
  234.     unlink(tempMail);
  235.     puthead(hp, nfo);
  236.     c = getc(fi);
  237.     while (c != EOF) {
  238.         putc(c, nfo);
  239.         c = getc(fi);
  240.     }
  241.     fflush(nfo);
  242.     if (ferror(nfo)) {
  243.         perror(tempMail);
  244.         fclose(nfo);
  245.         fclose(nfi);
  246.         return(fi);
  247.     }
  248.     fclose(nfo);
  249.     fclose(fi);
  250.     rewind(nfi);
  251.     return(nfi);
  252. }
  253.  
  254. /*
  255.  * Dump the to, subj, cc header on the
  256.  * passed file buffer.
  257.  */
  258.  
  259. puthead(hp, fo)
  260.     struct header *hp;
  261.     FILE *fo;
  262. {
  263.     if (hp->h_to != NOSTR)
  264.         fprintf(fo, "To: %s\n", hp->h_to);
  265.     if (hp->h_subj != NOSTR)
  266.         fprintf(fo, "Subj: %s\n", hp->h_subj);
  267.     if (hp->h_cc != NOSTR)
  268.         fprintf(fo, "Cc: %s\n", hp->h_cc);
  269.     if (hp->h_to != NOSTR || hp->h_subj != NOSTR || hp->h_cc != NOSTR)
  270.         putc('\n', fo);
  271.     return(0);
  272. }
  273.  
  274. /*
  275.  * Save the outgoing mail on the passed file.
  276.  */
  277.  
  278. savemail(name, hp, fi, tolist)
  279.     char name[], **tolist;
  280.     struct header *hp;
  281.     FILE *fi;
  282. {
  283.     register FILE *fo;
  284.     register int c;
  285.     long now;
  286.  
  287.     if ((fo = fopen(name, "a")) == NULL) {
  288.         perror(name);
  289.         return(-1);
  290.     }
  291.     time(&now);
  292.     fprintf(fo, "From %s %s", *(tolist+1), ctime(&now));
  293.     rewind(fi);
  294.     for (c = getc(fi); c != EOF; c = getc(fi))
  295.         putc(c, fo);
  296.     fprintf(fo, "\n");
  297.     fflush(fo);
  298.     if (ferror(fo))
  299.         perror(name);
  300.     fclose(fo);
  301.     return(0);
  302. }
  303.