|
|
1.1 ! root 1: # ! 2: ! 3: #include "rcv.h" ! 4: #ifdef VMUNIX ! 5: #include <wait.h> ! 6: #endif ! 7: ! 8: /* ! 9: * Mail -- a mail program ! 10: * ! 11: * Mail to others. ! 12: */ ! 13: ! 14: /* ! 15: * Send message described by the passed pointer to the ! 16: * passed output buffer. Return -1 on error, but normally ! 17: * the number of lines written. ! 18: */ ! 19: ! 20: send(mailp, obuf) ! 21: struct message *mailp; ! 22: FILE *obuf; ! 23: { ! 24: register struct message *mp; ! 25: register int t; ! 26: unsigned int c; ! 27: FILE *ibuf; ! 28: int lc; ! 29: ! 30: mp = mailp; ! 31: ibuf = setinput(mp); ! 32: c = msize(mp); ! 33: lc = 0; ! 34: while (c-- > 0) { ! 35: putc(t = getc(ibuf), obuf); ! 36: if (t == '\n') ! 37: lc++; ! 38: if (ferror(obuf)) ! 39: return(-1); ! 40: } ! 41: return(lc); ! 42: } ! 43: ! 44: /* ! 45: * Interface between the argument list and the mail1 routine ! 46: * which does all the dirty work. ! 47: */ ! 48: ! 49: mail(people) ! 50: char **people; ! 51: { ! 52: register char *cp2; ! 53: register int s; ! 54: char *buf, **ap; ! 55: struct header head; ! 56: ! 57: for (s = 0, ap = people; *ap != (char *) -1; ap++) ! 58: s += strlen(*ap) + 1; ! 59: buf = salloc(s+1); ! 60: cp2 = buf; ! 61: for (ap = people; *ap != (char *) -1; ap++) { ! 62: cp2 = copy(*ap, cp2); ! 63: *cp2++ = ' '; ! 64: } ! 65: if (cp2 != buf) ! 66: cp2--; ! 67: *cp2 = '\0'; ! 68: head.h_to = buf; ! 69: head.h_subject = NOSTR; ! 70: head.h_cc = NOSTR; ! 71: head.h_bcc = NOSTR; ! 72: head.h_seq = 0; ! 73: mail1(&head); ! 74: return(0); ! 75: } ! 76: ! 77: ! 78: /* ! 79: * Send mail to a bunch of user names. The interface is through ! 80: * the mail routine below. ! 81: */ ! 82: ! 83: sendmail(str) ! 84: char *str; ! 85: { ! 86: register char **ap; ! 87: char *bufp; ! 88: register int t; ! 89: struct header head; ! 90: ! 91: if (blankline(str)) ! 92: head.h_to = NOSTR; ! 93: else ! 94: head.h_to = str; ! 95: head.h_subject = NOSTR; ! 96: head.h_cc = NOSTR; ! 97: head.h_bcc = NOSTR; ! 98: head.h_seq = 0; ! 99: mail1(&head); ! 100: return(0); ! 101: } ! 102: ! 103: /* ! 104: * Mail a message on standard input to the people indicated ! 105: * in the passed header. (Internal interface). ! 106: */ ! 107: ! 108: mail1(hp) ! 109: struct header *hp; ! 110: { ! 111: register char *cp; ! 112: int pid, i, s, p, gotcha; ! 113: char **namelist; ! 114: struct name *to, *np; ! 115: FILE *mtf, *postage; ! 116: int remote = rflag != NOSTR || rmail; ! 117: char **t; ! 118: ! 119: /* ! 120: * Collect user's mail from standard input. ! 121: * Get the result as mtf. ! 122: */ ! 123: ! 124: pid = -1; ! 125: if ((mtf = collect(hp)) == NULL) ! 126: return(-1); ! 127: hp->h_seq = 1; ! 128: if (hp->h_subject == NOSTR) ! 129: hp->h_subject = sflag; ! 130: if (fsize(mtf) == 0 && hp->h_subject == NOSTR) { ! 131: printf("No message !?!\n"); ! 132: goto out; ! 133: } ! 134: if (intty && value("askcc") != NOSTR) ! 135: grabh(hp, GCC); ! 136: else if (intty) { ! 137: printf("EOT\n"); ! 138: flush(); ! 139: } ! 140: ! 141: /* ! 142: * Now, take the user names from the combined ! 143: * to and cc lists and do all the alias ! 144: * processing. ! 145: */ ! 146: ! 147: senderr = 0; ! 148: to = usermap(cat(extract(hp->h_bcc, GBCC), ! 149: cat(extract(hp->h_to, GTO), extract(hp->h_cc, GCC)))); ! 150: if (to == NIL) { ! 151: printf("No recipients specified\n"); ! 152: goto topdog; ! 153: } ! 154: ! 155: /* ! 156: * Look through the recipient list for names with /'s ! 157: * in them which we write to as files directly. ! 158: */ ! 159: ! 160: to = outof(to, mtf, hp); ! 161: rewind(mtf); ! 162: to = verify(to); ! 163: if (senderr && !remote) { ! 164: topdog: ! 165: ! 166: if (fsize(mtf) != 0) { ! 167: remove(deadletter); ! 168: exwrite(deadletter, mtf, 1); ! 169: rewind(mtf); ! 170: } ! 171: } ! 172: for (gotcha = 0, np = to; np != NIL; np = np->n_flink) ! 173: if ((np->n_type & GDEL) == 0) { ! 174: gotcha++; ! 175: break; ! 176: } ! 177: if (!gotcha) ! 178: goto out; ! 179: to = elide(to); ! 180: mechk(to); ! 181: if (count(to) > 1) ! 182: hp->h_seq++; ! 183: if (hp->h_seq > 0 && !remote) { ! 184: fixhead(hp, to); ! 185: if (fsize(mtf) == 0) ! 186: printf("Null message body; hope that's ok\n"); ! 187: if ((mtf = infix(hp, mtf)) == NULL) { ! 188: fprintf(stderr, ". . . message lost, sorry.\n"); ! 189: return(-1); ! 190: } ! 191: } ! 192: namelist = unpack(to); ! 193: if (debug) { ! 194: printf("Recipients of message:\n"); ! 195: for (t = namelist; *t != NOSTR; t++) ! 196: printf(" \"%s\"", *t); ! 197: printf("\n"); ! 198: fflush(stdout); ! 199: return; ! 200: } ! 201: if ((cp = value("record")) != NOSTR) ! 202: savemail(expand(cp), hp, mtf); ! 203: ! 204: /* ! 205: * Wait, to absorb a potential zombie, then ! 206: * fork, set up the temporary mail file as standard ! 207: * input for "mail" and exec with the user list we generated ! 208: * far above. Return the process id to caller in case he ! 209: * wants to await the completion of mail. ! 210: */ ! 211: ! 212: #ifdef VMUNIX ! 213: while (wait3(&s, WNOHANG, 0) > 0) ! 214: ; ! 215: #else ! 216: wait(&s); ! 217: #endif ! 218: rewind(mtf); ! 219: pid = fork(); ! 220: if (pid == -1) { ! 221: perror("fork"); ! 222: remove(deadletter); ! 223: exwrite(deadletter, mtf, 1); ! 224: goto out; ! 225: } ! 226: if (pid == 0) { ! 227: #ifdef SIGTSTP ! 228: if (remote == 0) { ! 229: signal(SIGTSTP, SIG_IGN); ! 230: signal(SIGTTIN, SIG_IGN); ! 231: signal(SIGTTOU, SIG_IGN); ! 232: } ! 233: #endif ! 234: for (i = SIGHUP; i <= SIGQUIT; i++) ! 235: signal(i, SIG_IGN); ! 236: if ((postage = fopen("/crp/kurt/postage", "a")) != NULL) { ! 237: fprintf(postage, "%s %d %d\n", myname, ! 238: count(to), fsize(mtf)); ! 239: fclose(postage); ! 240: } ! 241: s = fileno(mtf); ! 242: for (i = 3; i < 15; i++) ! 243: if (i != s) ! 244: close(i); ! 245: close(0); ! 246: dup(s); ! 247: close(s); ! 248: #ifdef CC ! 249: submit(getpid()); ! 250: #endif CC ! 251: #ifdef DELIVERMAIL ! 252: execv(DELIVERMAIL, namelist); ! 253: #endif DELIVERMAIL ! 254: execv(MAIL, namelist); ! 255: perror(MAIL); ! 256: exit(1); ! 257: } ! 258: ! 259: out: ! 260: if (remote) { ! 261: while ((p = wait(&s)) != pid && p != -1) ! 262: ; ! 263: if (s != 0) ! 264: senderr++; ! 265: pid = 0; ! 266: } ! 267: fclose(mtf); ! 268: return(pid); ! 269: } ! 270: ! 271: /* ! 272: * Fix the header by glopping all of the expanded names from ! 273: * the distribution list into the appropriate fields. ! 274: * If there are any ARPA net recipients in the message, ! 275: * we must insert commas, alas. ! 276: */ ! 277: ! 278: fixhead(hp, tolist) ! 279: struct header *hp; ! 280: struct name *tolist; ! 281: { ! 282: register struct name *nlist; ! 283: register int f; ! 284: register struct name *np; ! 285: ! 286: for (f = 0, np = tolist; np != NIL; np = np->n_flink) ! 287: if (any('@', np->n_name)) { ! 288: f |= GCOMMA; ! 289: break; ! 290: } ! 291: ! 292: if (debug && f & GCOMMA) ! 293: fprintf(stderr, "Should be inserting commas in recip lists\n"); ! 294: hp->h_to = detract(tolist, GTO|f); ! 295: hp->h_cc = detract(tolist, GCC|f); ! 296: } ! 297: ! 298: /* ! 299: * Prepend a header in front of the collected stuff ! 300: * and return the new file. ! 301: */ ! 302: ! 303: FILE * ! 304: infix(hp, fi) ! 305: struct header *hp; ! 306: FILE *fi; ! 307: { ! 308: extern char tempMail[]; ! 309: register FILE *nfo, *nfi; ! 310: register int c; ! 311: ! 312: if ((nfo = fopen(tempMail, "w")) == NULL) { ! 313: perror(tempMail); ! 314: return(fi); ! 315: } ! 316: if ((nfi = fopen(tempMail, "r")) == NULL) { ! 317: perror(tempMail); ! 318: fclose(nfo); ! 319: return(fi); ! 320: } ! 321: remove(tempMail); ! 322: puthead(hp, nfo, GTO|GSUBJECT|GCC|GNL); ! 323: rewind(fi); ! 324: c = getc(fi); ! 325: while (c != EOF) { ! 326: putc(c, nfo); ! 327: c = getc(fi); ! 328: } ! 329: if (ferror(fi)) { ! 330: perror("read"); ! 331: fprintf(stderr, "Please notify Kurt Shoens\n"); ! 332: return(fi); ! 333: } ! 334: fflush(nfo); ! 335: if (ferror(nfo)) { ! 336: perror(tempMail); ! 337: fclose(nfo); ! 338: fclose(nfi); ! 339: return(fi); ! 340: } ! 341: fclose(nfo); ! 342: fclose(fi); ! 343: rewind(nfi); ! 344: return(nfi); ! 345: } ! 346: ! 347: /* ! 348: * Dump the to, subject, cc header on the ! 349: * passed file buffer. ! 350: */ ! 351: ! 352: puthead(hp, fo, w) ! 353: struct header *hp; ! 354: FILE *fo; ! 355: { ! 356: register int gotcha; ! 357: ! 358: gotcha = 0; ! 359: if (hp->h_to != NOSTR && w & GTO) ! 360: fprintf(fo, "To: "), fmt(hp->h_to, fo), gotcha++; ! 361: if (hp->h_subject != NOSTR && w & GSUBJECT) ! 362: fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++; ! 363: if (hp->h_cc != NOSTR && w & GCC) ! 364: fprintf(fo, "Cc: "), fmt(hp->h_cc, fo), gotcha++; ! 365: if (hp->h_bcc != NOSTR && w & GBCC) ! 366: fprintf(fo, "Bcc: "), fmt(hp->h_bcc, fo), gotcha++; ! 367: if (gotcha && w & GNL) ! 368: putc('\n', fo); ! 369: return(0); ! 370: } ! 371: ! 372: /* ! 373: * Format the given text to not exceed 72 characters. ! 374: */ ! 375: ! 376: fmt(str, fo) ! 377: register char *str; ! 378: register FILE *fo; ! 379: { ! 380: register int col; ! 381: register char *cp; ! 382: ! 383: cp = str; ! 384: col = 0; ! 385: while (*cp) { ! 386: if (*cp == ' ' && col > 65) { ! 387: fprintf(fo, "\n "); ! 388: col = 4; ! 389: cp++; ! 390: continue; ! 391: } ! 392: putc(*cp++, fo); ! 393: col++; ! 394: } ! 395: putc('\n', fo); ! 396: } ! 397: ! 398: /* ! 399: * Save the outgoing mail on the passed file. ! 400: */ ! 401: ! 402: savemail(name, hp, fi) ! 403: char name[]; ! 404: struct header *hp; ! 405: FILE *fi; ! 406: { ! 407: register FILE *fo; ! 408: register int c; ! 409: long now; ! 410: char *n; ! 411: ! 412: if ((fo = fopen(name, "a")) == NULL) { ! 413: perror(name); ! 414: return(-1); ! 415: } ! 416: time(&now); ! 417: n = rflag; ! 418: if (n == NOSTR) ! 419: n = myname; ! 420: fprintf(fo, "From %s %s", n, ctime(&now)); ! 421: rewind(fi); ! 422: for (c = getc(fi); c != EOF; c = getc(fi)) ! 423: putc(c, fo); ! 424: fprintf(fo, "\n"); ! 425: fflush(fo); ! 426: if (ferror(fo)) ! 427: perror(name); ! 428: fclose(fo); ! 429: return(0); ! 430: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.