1: #
   2: 
   3: #include "rcv.h"
   4: #ifdef VMUNIX
   5: #include <wait.h>
   6: #endif
   7: #include <ctype.h>
   8: #include <sys/stat.h>
   9: 
  10: /*
  11:  * Mail -- a mail program
  12:  *
  13:  * Mail to others.
  14:  */
  15: 
  16: static char *SccsId = "@(#)send.c	2.12 7/2/83";
  17: 
  18: /*
  19:  * Send message described by the passed pointer to the
  20:  * passed output buffer.  Return -1 on error, but normally
  21:  * the number of lines written.  Adjust the status: field
  22:  * if need be.  If doign is set, suppress ignored header fields.
  23:  */
  24: send(mailp, obuf, doign)
  25:     struct message *mailp;
  26:     FILE *obuf;
  27: {
  28:     register struct message *mp;
  29:     register int t;
  30:     long c;
  31:     FILE *ibuf;
  32:     char line[LINESIZE], field[BUFSIZ];
  33:     int lc, ishead, infld, fline, dostat;
  34:     char *cp, *cp2;
  35: 
  36:     mp = mailp;
  37:     ibuf = setinput(mp);
  38:     c = mp->m_size;
  39:     ishead = 1;
  40:     dostat = 1;
  41:     infld = 0;
  42:     fline = 1;
  43:     lc = 0;
  44:     while (c > 0L) {
  45:         fgets(line, LINESIZE, ibuf);
  46:         c -= (long) strlen(line);
  47:         lc++;
  48:         if (ishead) {
  49:             /*
  50: 			 * First line is the From line, so no headers
  51: 			 * there to worry about
  52: 			 */
  53:             if (fline) {
  54:                 fline = 0;
  55:                 goto writeit;
  56:             }
  57:             /*
  58: 			 * If line is blank, we've reached end of
  59: 			 * headers, so force out status: field
  60: 			 * and note that we are no longer in header
  61: 			 * fields
  62: 			 */
  63:             if (line[0] == '\n') {
  64:                 if (dostat) {
  65:                     statusput(mailp, obuf, doign);
  66:                     dostat = 0;
  67:                 }
  68:                 ishead = 0;
  69:                 goto writeit;
  70:             }
  71:             /*
  72: 			 * If this line is a continuation (via space or tab)
  73: 			 * of a previous header field, just echo it
  74: 			 * (unless the field should be ignored).
  75: 			 */
  76:             if (infld && (isspace(line[0]) || line[0] == '\t')) {
  77:                 if (doign && isign(field)) continue;
  78:                 goto writeit;
  79:             }
  80:             infld = 0;
  81:             /*
  82: 			 * If we are no longer looking at real
  83: 			 * header lines, force out status:
  84: 			 * This happens in uucp style mail where
  85: 			 * there are no headers at all.
  86: 			 */
  87:             if (!headerp(line)) {
  88:                 if (dostat) {
  89:                     statusput(mailp, obuf, doign);
  90:                     dostat = 0;
  91:                 }
  92:                 putc('\n', obuf);
  93:                 ishead = 0;
  94:                 goto writeit;
  95:             }
  96:             infld++;
  97:             /*
  98: 			 * Pick up the header field.
  99: 			 * If it is an ignored field and
 100: 			 * we care about such things, skip it.
 101: 			 */
 102:             cp = line;
 103:             cp2 = field;
 104:             while (*cp && *cp != ':' && !isspace(*cp))
 105:                 *cp2++ = *cp++;
 106:             *cp2 = 0;
 107:             if (doign && isign(field))
 108:                 continue;
 109:             /*
 110: 			 * If the field is "status," go compute and print the
 111: 			 * real Status: field
 112: 			 */
 113:             if (icequal(field, "status")) {
 114:                 if (dostat) {
 115:                     statusput(mailp, obuf, doign);
 116:                     dostat = 0;
 117:                 }
 118:                 continue;
 119:             }
 120:         }
 121: writeit:
 122:         fputs(line, obuf);
 123:         if (ferror(obuf))
 124:             return(-1);
 125:     }
 126:     if (ferror(obuf))
 127:         return(-1);
 128:     if (ishead && (mailp->m_flag & MSTATUS))
 129:         printf("failed to fix up status field\n");
 130:     return(lc);
 131: }
 132: 
 133: /*
 134:  * Test if the passed line is a header line, RFC 733 style.
 135:  */
 136: headerp(line)
 137:     register char *line;
 138: {
 139:     register char *cp = line;
 140: 
 141:     while (*cp && !isspace(*cp) && *cp != ':')
 142:         cp++;
 143:     while (*cp && isspace(*cp))
 144:         cp++;
 145:     return(*cp == ':');
 146: }
 147: 
 148: /*
 149:  * Output a reasonable looking status field.
 150:  * But if "status" is ignored and doign, forget it.
 151:  */
 152: statusput(mp, obuf, doign)
 153:     register struct message *mp;
 154:     register FILE *obuf;
 155: {
 156:     char statout[3];
 157: 
 158:     if (doign && isign("status"))
 159:         return;
 160:     if ((mp->m_flag & (MNEW|MREAD)) == MNEW)
 161:         return;
 162:     if (mp->m_flag & MREAD)
 163:         strcpy(statout, "R");
 164:     else
 165:         strcpy(statout, "");
 166:     if ((mp->m_flag & MNEW) == 0)
 167:         strcat(statout, "O");
 168:     fprintf(obuf, "Status: %s\n", statout);
 169: }
 170: 
 171: 
 172: /*
 173:  * Interface between the argument list and the mail1 routine
 174:  * which does all the dirty work.
 175:  */
 176: 
 177: mail(people)
 178:     char **people;
 179: {
 180:     register char *cp2;
 181:     register int s;
 182:     char *buf, **ap;
 183:     struct header head;
 184: 
 185:     for (s = 0, ap = people; *ap != (char *) -1; ap++)
 186:         s += strlen(*ap) + 1;
 187:     buf = salloc(s+1);
 188:     cp2 = buf;
 189:     for (ap = people; *ap != (char *) -1; ap++) {
 190:         cp2 = copy(*ap, cp2);
 191:         *cp2++ = ' ';
 192:     }
 193:     if (cp2 != buf)
 194:         cp2--;
 195:     *cp2 = '\0';
 196:     head.h_to = buf;
 197:     head.h_subject = NOSTR;
 198:     head.h_cc = NOSTR;
 199:     head.h_bcc = NOSTR;
 200:     head.h_seq = 0;
 201:     mail1(&head);
 202:     return(0);
 203: }
 204: 
 205: 
 206: /*
 207:  * Send mail to a bunch of user names.  The interface is through
 208:  * the mail routine below.
 209:  */
 210: 
 211: sendmail(str)
 212:     char *str;
 213: {
 214:     register char **ap;
 215:     char *bufp;
 216:     register int t;
 217:     struct header head;
 218: 
 219:     if (blankline(str))
 220:         head.h_to = NOSTR;
 221:     else
 222:         head.h_to = str;
 223:     head.h_subject = NOSTR;
 224:     head.h_cc = NOSTR;
 225:     head.h_bcc = NOSTR;
 226:     head.h_seq = 0;
 227:     mail1(&head);
 228:     return(0);
 229: }
 230: 
 231: /*
 232:  * Mail a message on standard input to the people indicated
 233:  * in the passed header.  (Internal interface).
 234:  */
 235: 
 236: mail1(hp)
 237:     struct header *hp;
 238: {
 239:     register char *cp;
 240:     int pid, i, s, p, gotcha;
 241:     char **namelist, *deliver;
 242:     struct name *to, *np;
 243:     struct stat sbuf;
 244:     FILE *mtf, *postage;
 245:     int remote = rflag != NOSTR || rmail;
 246:     char **t;
 247: 
 248:     /*
 249: 	 * Collect user's mail from standard input.
 250: 	 * Get the result as mtf.
 251: 	 */
 252: 
 253:     pid = -1;
 254:     if ((mtf = collect(hp)) == NULL)
 255:         return(-1);
 256:     hp->h_seq = 1;
 257:     if (hp->h_subject == NOSTR)
 258:         hp->h_subject = sflag;
 259:     if (intty && value("askcc") != NOSTR)
 260:         grabh(hp, GCC);
 261:     else if (intty) {
 262:         printf("EOT\n");
 263:         flush();
 264:     }
 265: 
 266:     /*
 267: 	 * Now, take the user names from the combined
 268: 	 * to and cc lists and do all the alias
 269: 	 * processing.
 270: 	 */
 271: 
 272:     senderr = 0;
 273:     to = usermap(cat(extract(hp->h_bcc, GBCC),
 274:         cat(extract(hp->h_to, GTO), extract(hp->h_cc, GCC))));
 275:     if (to == NIL) {
 276:         printf("No recipients specified\n");
 277:         goto topdog;
 278:     }
 279: 
 280:     /*
 281: 	 * Look through the recipient list for names with /'s
 282: 	 * in them which we write to as files directly.
 283: 	 */
 284: 
 285:     to = outof(to, mtf, hp);
 286:     rewind(mtf);
 287:     to = verify(to);
 288:     if (senderr && !remote) {
 289: topdog:
 290: 
 291:         if (fsize(mtf) != 0) {
 292:             remove(deadletter);
 293:             exwrite(deadletter, mtf, 1);
 294:             rewind(mtf);
 295:         }
 296:     }
 297:     for (gotcha = 0, np = to; np != NIL; np = np->n_flink)
 298:         if ((np->n_type & GDEL) == 0) {
 299:             gotcha++;
 300:             break;
 301:         }
 302:     if (!gotcha)
 303:         goto out;
 304:     to = elide(to);
 305:     mechk(to);
 306:     if (count(to) > 1)
 307:         hp->h_seq++;
 308:     if (hp->h_seq > 0 && !remote) {
 309:         fixhead(hp, to);
 310:         if (fsize(mtf) == 0)
 311:             if (hp->h_subject == NOSTR)
 312:             printf("No message, no subject; hope that's ok\n");
 313:             else
 314:             printf("Null message body; hope that's ok\n");
 315:         if ((mtf = infix(hp, mtf)) == NULL) {
 316:             fprintf(stderr, ". . . message lost, sorry.\n");
 317:             return(-1);
 318:         }
 319:     }
 320:     namelist = unpack(to);
 321:     if (debug) {
 322:         printf("Recipients of message:\n");
 323:         for (t = namelist; *t != NOSTR; t++)
 324:             printf(" \"%s\"", *t);
 325:         printf("\n");
 326:         fflush(stdout);
 327:         return;
 328:     }
 329:     if ((cp = value("record")) != NOSTR)
 330:         savemail(expand(cp), hp, mtf);
 331: 
 332:     /*
 333: 	 * Wait, to absorb a potential zombie, then
 334: 	 * fork, set up the temporary mail file as standard
 335: 	 * input for "mail" and exec with the user list we generated
 336: 	 * far above. Return the process id to caller in case he
 337: 	 * wants to await the completion of mail.
 338: 	 */
 339: 
 340: #ifdef VMUNIX
 341: #ifdef  pdp11
 342:     while (wait2(&s, WNOHANG) > 0)
 343: #endif
 344: #if defined(vax) || defined(sun)
 345:     while (wait3(&s, WNOHANG, 0) > 0)
 346: #endif
 347:         ;
 348: #else
 349:     wait(&s);
 350: #endif
 351:     rewind(mtf);
 352:     pid = fork();
 353:     if (pid == -1) {
 354:         perror("fork");
 355:         remove(deadletter);
 356:         exwrite(deadletter, mtf, 1);
 357:         goto out;
 358:     }
 359:     if (pid == 0) {
 360:         sigchild();
 361: #ifdef SIGTSTP
 362:         if (remote == 0) {
 363:             sigset(SIGTSTP, SIG_IGN);
 364:             sigset(SIGTTIN, SIG_IGN);
 365:             sigset(SIGTTOU, SIG_IGN);
 366:         }
 367: #endif
 368:         for (i = SIGHUP; i <= SIGQUIT; i++)
 369:             sigset(i, SIG_IGN);
 370:         if (!stat(POSTAGE, &sbuf))
 371:             if ((postage = fopen(POSTAGE, "a")) != NULL) {
 372:                 fprintf(postage, "%s %d %d\n", myname,
 373:                     count(to), fsize(mtf));
 374:                 fclose(postage);
 375:             }
 376:         s = fileno(mtf);
 377:         for (i = 3; i < 15; i++)
 378:             if (i != s)
 379:                 close(i);
 380:         close(0);
 381:         dup(s);
 382:         close(s);
 383: #ifdef CC
 384:         submit(getpid());
 385: #endif CC
 386: #ifdef SENDMAIL
 387:         if ((deliver = value("sendmail")) == NOSTR)
 388:             deliver = SENDMAIL;
 389:         execv(deliver, namelist);
 390: #endif SENDMAIL
 391:         execv(MAIL, namelist);
 392:         perror(MAIL);
 393:         exit(1);
 394:     }
 395: 
 396: out:
 397:     if (remote || (value("verbose") != NOSTR)) {
 398:         while ((p = wait(&s)) != pid && p != -1)
 399:             ;
 400:         if (s != 0)
 401:             senderr++;
 402:         pid = 0;
 403:     }
 404:     fclose(mtf);
 405:     return(pid);
 406: }
 407: 
 408: /*
 409:  * Fix the header by glopping all of the expanded names from
 410:  * the distribution list into the appropriate fields.
 411:  * If there are any ARPA net recipients in the message,
 412:  * we must insert commas, alas.
 413:  */
 414: 
 415: fixhead(hp, tolist)
 416:     struct header *hp;
 417:     struct name *tolist;
 418: {
 419:     register struct name *nlist;
 420:     register int f;
 421:     register struct name *np;
 422: 
 423:     for (f = 0, np = tolist; np != NIL; np = np->n_flink)
 424:         if (any('@', np->n_name)) {
 425:             f |= GCOMMA;
 426:             break;
 427:         }
 428: 
 429:     if (debug && f & GCOMMA)
 430:         fprintf(stderr, "Should be inserting commas in recip lists\n");
 431:     hp->h_to = detract(tolist, GTO|f);
 432:     hp->h_cc = detract(tolist, GCC|f);
 433: }
 434: 
 435: /*
 436:  * Prepend a header in front of the collected stuff
 437:  * and return the new file.
 438:  */
 439: 
 440: FILE *
 441: infix(hp, fi)
 442:     struct header *hp;
 443:     FILE *fi;
 444: {
 445:     extern char tempMail[];
 446:     register FILE *nfo, *nfi;
 447:     register int c;
 448: 
 449:     rewind(fi);
 450:     if ((nfo = fopen(tempMail, "w")) == NULL) {
 451:         perror(tempMail);
 452:         return(fi);
 453:     }
 454:     if ((nfi = fopen(tempMail, "r")) == NULL) {
 455:         perror(tempMail);
 456:         fclose(nfo);
 457:         return(fi);
 458:     }
 459:     remove(tempMail);
 460:     puthead(hp, nfo, GTO|GSUBJECT|GCC|GNL);
 461:     c = getc(fi);
 462:     while (c != EOF) {
 463:         putc(c, nfo);
 464:         c = getc(fi);
 465:     }
 466:     if (ferror(fi)) {
 467:         perror("read");
 468:         return(fi);
 469:     }
 470:     fflush(nfo);
 471:     if (ferror(nfo)) {
 472:         perror(tempMail);
 473:         fclose(nfo);
 474:         fclose(nfi);
 475:         return(fi);
 476:     }
 477:     fclose(nfo);
 478:     fclose(fi);
 479:     rewind(nfi);
 480:     return(nfi);
 481: }
 482: 
 483: /*
 484:  * Dump the to, subject, cc header on the
 485:  * passed file buffer.
 486:  */
 487: 
 488: puthead(hp, fo, w)
 489:     struct header *hp;
 490:     FILE *fo;
 491: {
 492:     register int gotcha;
 493: 
 494:     gotcha = 0;
 495:     if (hp->h_to != NOSTR && w & GTO)
 496:         fmt("To: ", hp->h_to, fo), gotcha++;
 497:     if (hp->h_subject != NOSTR && w & GSUBJECT)
 498:         fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
 499:     if (hp->h_cc != NOSTR && w & GCC)
 500:         fmt("Cc: ", hp->h_cc, fo), gotcha++;
 501:     if (hp->h_bcc != NOSTR && w & GBCC)
 502:         fmt("Bcc: ", hp->h_bcc, fo), gotcha++;
 503:     if (gotcha && w & GNL)
 504:         putc('\n', fo);
 505:     return(0);
 506: }
 507: 
 508: /*
 509:  * Format the given text to not exceed 72 characters.
 510:  */
 511: 
 512: fmt(str, txt, fo)
 513:     register char *str, *txt;
 514:     register FILE *fo;
 515: {
 516:     register int col;
 517:     register char *bg, *bl, *pt, ch;
 518: 
 519:     col = strlen(str);
 520:     if (col)
 521:         fprintf(fo, "%s", str);
 522:     pt = bg = txt;
 523:     bl = 0;
 524:     while (*bg) {
 525:         pt++;
 526:         if (++col >72) {
 527:             if (!bl) {
 528:                 bl = bg;
 529:                 while (*bl && !isspace(*bl))
 530:                     bl++;
 531:             }
 532:             if (!*bl)
 533:                 goto finish;
 534:             ch = *bl;
 535:             *bl = '\0';
 536:             fprintf(fo, "%s\n    ", bg);
 537:             col = 4;
 538:             *bl = ch;
 539:             pt = bg = ++bl;
 540:             bl = 0;
 541:         }
 542:         if (!*pt) {
 543: finish:
 544:             fprintf(fo, "%s\n", bg);
 545:             return;
 546:         }
 547:         if (isspace(*pt))
 548:             bl = pt;
 549:     }
 550: }
 551: 
 552: /*
 553:  * Save the outgoing mail on the passed file.
 554:  */
 555: 
 556: savemail(name, hp, fi)
 557:     char name[];
 558:     struct header *hp;
 559:     FILE *fi;
 560: {
 561:     register FILE *fo;
 562:     register int c;
 563:     long now;
 564:     char *n;
 565: 
 566:     if ((fo = fopen(name, "a")) == NULL) {
 567:         perror(name);
 568:         return(-1);
 569:     }
 570:     time(&now);
 571:     n = rflag;
 572:     if (n == NOSTR)
 573:         n = myname;
 574:     fprintf(fo, "From %s %s", n, ctime(&now));
 575:     rewind(fi);
 576:     for (c = getc(fi); c != EOF; c = getc(fi))
 577:         putc(c, fo);
 578:     fprintf(fo, "\n");
 579:     fflush(fo);
 580:     if (ferror(fo))
 581:         perror(name);
 582:     fclose(fo);
 583:     return(0);
 584: }

Defined functions

fixhead defined in line 415; used 1 times
fmt defined in line 512; used 3 times
headerp defined in line 136; used 1 times
  • in line 87
infix defined in line 440; used 2 times
mail defined in line 177; used 1 times
mail1 defined in line 236; used 4 times
puthead defined in line 488; used 4 times
savemail defined in line 556; used 1 times
sendmail defined in line 211; used 2 times
statusput defined in line 152; used 3 times

Defined variables

SccsId defined in line 16; never used
Last modified: 1983-07-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1522
Valid CSS Valid XHTML 1.0 Strict