Annotation of researchv10no/lbin/mailx/send.c, revision 1.1.1.1

1.1       root        1: #ident "@(#)send.c     1.6 'attmail mail(1) command'"
                      2: #ident "@(#)mailx:send.c       1.11.1.2"
                      3: /*     Copyright (c) 1984 AT&T */
                      4: /*       All Rights Reserved   */
                      5: 
                      6: /*     THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T     */
                      7: /*     The copyright notice above does not evidence any        */
                      8: /*     actual or intended publication of such source code.     */
                      9: 
                     10: #ident "@(#)mailx:send.c       1.11.1.1"
                     11: 
                     12: #include "rcv.h"
                     13: 
                     14: /*
                     15:  * mailx -- a modified version of a University of California at Berkeley
                     16:  *     mail program
                     17:  *
                     18:  * Mail to others.
                     19:  */
                     20: 
                     21: static void            fmt();
                     22: static FILE            *infix();
                     23: static void            statusput();
                     24: static int             savemail();
                     25: static int             sendmail();
                     26: static int             Sendmail();
                     27: 
                     28: static off_t textpos;
                     29: 
                     30: /*
                     31:  * Send message described by the passed pointer to the
                     32:  * passed output buffer.  Return -1 on error, but normally
                     33:  * the number of lines written.  Adjust the status: field
                     34:  * if need be.  If doign is set, suppress ignored header fields.
                     35:  */
                     36: long
                     37: send(mailp, obuf, doign)
                     38:        struct message *mailp;
                     39:        FILE *obuf;
                     40: {
                     41:        register struct message *mp;
                     42:        long clen, n, c;
                     43:        FILE *ibuf;
                     44:        char line[LINESIZE+1], field[BUFSIZ];
                     45:        int ishead, infld, fline, dostat, nread, unused;
                     46:        char *cp, *cp2;
                     47:        int oldign = 0; /* previous line was ignored */
                     48:        long lc;
                     49: 
                     50:        mp = mailp;
                     51:        ibuf = setinput(mp);
                     52:        c = mp->m_size;
                     53:        ishead = 1;
                     54:        dostat = 1;
                     55:        infld = 0;
                     56:        fline = 1;
                     57:        lc = 0;
                     58:        clearerr(obuf);
                     59:        while (c > 0L) {
                     60:                nread = getline(line, LINESIZE, ibuf, &unused);
                     61:                c -= nread;
                     62:                lc++;
                     63:                if (ishead) {
                     64:                        /*
                     65:                         * First line is the From line, so no headers
                     66:                         * there to worry about
                     67:                         */
                     68:                        if (fline) {
                     69:                                fline = 0;
                     70:                                goto writeit;
                     71:                        }
                     72:                        /*
                     73:                         * If line is blank, we've reached end of
                     74:                         * headers, so force out status: field
                     75:                         * and note that we are no longer in header
                     76:                         * fields
                     77:                         */
                     78:                        if (line[0] == '\n') {
                     79:                                if (dostat) {
                     80:                                        statusput(mailp, obuf, doign);
                     81:                                        dostat = 0;
                     82:                                }
                     83:                                ishead = 0;
                     84:                                putc('\n', obuf);
                     85:                                continue;
                     86:                        }
                     87:                        /*
                     88:                         * If this line is a continuation
                     89:                         * of a previous header field, just echo it.
                     90:                         */
                     91:                        if (isspace(line[0]) && infld)
                     92:                                if (oldign)
                     93:                                        continue;
                     94:                                else
                     95:                                        goto writeit;
                     96:                        infld = 0;
                     97:                        /*
                     98:                         * If we are no longer looking at real
                     99:                         * header lines, force out status:
                    100:                         * This happens in uucp style mail where
                    101:                         * there are no headers at all.
                    102:                         */
                    103:                        if (!headerp(line)) {
                    104:                                if (dostat) {
                    105:                                        statusput(mailp, obuf, doign);
                    106:                                        dostat = 0;
                    107:                                }
                    108:                                putc('\n', obuf);
                    109:                                ishead = 0;
                    110:                                goto writeit;
                    111:                        }
                    112:                        infld++;
                    113:                        /*
                    114:                         * Pick up the header field.
                    115:                         * If it is an ignored field and
                    116:                         * we care about such things, skip it.
                    117:                         */
                    118:                        cp = line;
                    119:                        cp2 = field;
                    120:                        while (*cp && *cp != ':' && !isspace(*cp))
                    121:                                *cp2++ = *cp++;
                    122:                        *cp2 = 0;
                    123:                        oldign = doign && isign(field);
                    124:                        if (oldign)
                    125:                                continue;
                    126:                        /*
                    127:                         * If the field is "status," go compute and print the
                    128:                         * real Status: field
                    129:                         */
                    130:                        if (icequal(field, "status")) {
                    131:                                if (dostat) {
                    132:                                        statusput(mailp, obuf, doign);
                    133:                                        dostat = 0;
                    134:                                }
                    135:                                continue;
                    136:                        }
                    137:                }
                    138: writeit:
                    139:                if ((!ishead) && (!(mp->m_text))) {
                    140:                        fwrite(line, 1, nread, obuf);           /* output first non-hdr */
                    141:                        if (ferror(obuf))
                    142:                                return(-1);
                    143:                        clen = mp->m_clen - nread;
                    144:                        n = clen < sizeof line ? clen : sizeof line;
                    145:                        for (;n > 0;) {
                    146:                                if ((n = fread(line, 1, n, ibuf)) <= 0) {
                    147:                                        fprintf(stderr, "\t(Unexpected end-of-file).\n");
                    148:                                        clen = 0;
                    149:                                } else {
                    150:                                        if (fwrite(line, 1, n, obuf) != n) {
                    151:                                                fprintf(stderr, "\t Error writing to the new file.\n");
                    152:                                                fflush(obuf);
                    153:                                                if (ferror(obuf))
                    154:                                                return (-1);
                    155:                                        }
                    156:                                }
                    157:                                clen -= n;
                    158:                                if (clen <= 0) {
                    159:                                        break;
                    160:                                }
                    161:                        }
                    162:                        c = 0L;
                    163:                } else {
                    164:                        fwrite(line, 1, nread, obuf);
                    165:                        if (ferror(obuf))
                    166:                                return(-1);
                    167:                }
                    168:        }
                    169:        fflush(obuf);
                    170:        if (ferror(obuf))
                    171:                return(-1);
                    172:        if (ishead && (mailp->m_flag & MSTATUS))
                    173:                printf("failed to fix up status field\n");
                    174:        return(lc);
                    175: }
                    176: 
                    177: /*
                    178:  * Test if the passed line is a header line, RFC 733 style.
                    179:  */
                    180: headerp(line)
                    181:        register char *line;
                    182: {
                    183:        register char *cp = line;
                    184: 
                    185:        if (*cp=='>' && strncmp(cp+1, "From", 4)==0)
                    186:                return(1);
                    187:        while (*cp && !isspace(*cp) && *cp != ':')
                    188:                cp++;
                    189:        while (*cp && isspace(*cp))
                    190:                cp++;
                    191:        return(*cp == ':');
                    192: }
                    193: 
                    194: /*
                    195:  * Output a reasonable looking status field.
                    196:  * But if "status" is ignored and doign, forget it.
                    197:  */
                    198: static void
                    199: statusput(mp, obuf, doign)
                    200:        register struct message *mp;
                    201:        register FILE *obuf;
                    202: {
                    203:        char statout[3];
                    204: 
                    205:        if (doign && isign("status"))
                    206:                return;
                    207:        if ((mp->m_flag & (MNEW|MREAD)) == MNEW)
                    208:                return;
                    209:        if (mp->m_flag & MREAD)
                    210:                strcpy(statout, "R");
                    211:        else
                    212:                strcpy(statout, "");
                    213:        if ((mp->m_flag & MNEW) == 0)
                    214:                strcat(statout, "O");
                    215:        fprintf(obuf, "Status: %s\n", statout);
                    216: }
                    217: 
                    218: /*
                    219:  * Interface between the argument list and the mail1 routine
                    220:  * which does all the dirty work.
                    221:  */
                    222: 
                    223: mail(people)
                    224:        char **people;
                    225: {
                    226:        register char *cp2;
                    227:        register int s;
                    228:        char *buf, **ap;
                    229:        struct header head;
                    230:        char recfile[128];
                    231: 
                    232:        for (s = 0, ap = people; *ap; ap++)
                    233:                s += strlen(*ap) + 2;
                    234:        buf = salloc((unsigned)(s+1));
                    235:        cp2 = buf;
                    236:        for (ap = people; *ap; ap++) {
                    237:                cp2 = copy(*ap, cp2);
                    238: /*             *cp2++ = ',';                   adb: not in our mail */
                    239:                *cp2++ = ' ';
                    240:        }
                    241:        *cp2 = '\0';
                    242:        head.h_to = buf;
                    243:        strncpy(recfile, buf, sizeof recfile);
                    244:        head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR;
                    245:        head.h_others = NOSTRPTR;
                    246:        head.h_seq = 0;
                    247:        mail1(&head, Fflag ? recfile : 0);
                    248:        return(0);
                    249: }
                    250: 
                    251: sendm(str)
                    252: char *str;
                    253: {
                    254:        if (value("flipm") != NOSTR)
                    255:                return(Sendmail(str));
                    256:        else return(sendmail(str));
                    257: }
                    258: 
                    259: Sendm(str)
                    260: char *str;
                    261: {
                    262:        if (value("flipm") != NOSTR)
                    263:                return(sendmail(str));
                    264:        else return(Sendmail(str));
                    265: }
                    266: 
                    267: /*
                    268:  * Send mail to a bunch of user names.  The interface is through
                    269:  * the mail routine below.
                    270:  */
                    271: static int
                    272: sendmail(str)
                    273:        char *str;
                    274: {
                    275:        struct header head;
                    276: 
                    277:        if (blankline(str))
                    278:                head.h_to = NOSTR;
                    279:        else
                    280:                head.h_to = addto(NOSTR, str);
                    281:        head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR;
                    282:        head.h_others = NOSTRPTR;
                    283:        head.h_seq = 0;
                    284:        mail1(&head, (char *) 0);
                    285:        return(0);
                    286: }
                    287: 
                    288: /*
                    289:  * Send mail to a bunch of user names.  The interface is through
                    290:  * the mail routine below.
                    291:  * save a copy of the letter
                    292:  */
                    293: static int
                    294: Sendmail(str)
                    295:        char *str;
                    296: {
                    297:        char recfile[128];
                    298:        struct header head;
                    299: 
                    300:        if (blankline(str))
                    301:                head.h_to = NOSTR;
                    302:        else
                    303:                head.h_to = addto(NOSTR, str);
                    304:        strncpy(recfile, head.h_to, sizeof recfile);
                    305:        head.h_subject = head.h_cc = head.h_bcc = head.h_defopt = NOSTR;
                    306:        head.h_others = NOSTRPTR;
                    307:        head.h_seq = 0;
                    308:        mail1(&head, recfile);
                    309:        return(0);
                    310: }
                    311: 
                    312: /*
                    313:  * Mail a message on standard input to the people indicated
                    314:  * in the passed header.  (Internal interface).
                    315:  */
                    316: void
                    317: mail1(hp, rec)
                    318:        struct header *hp;
                    319:        char *rec;
                    320: {
                    321:        pid_t p, pid;
                    322:        int i, s, gotcha;
                    323:        char **namelist, *deliver;
                    324:        struct name *to, *np;
                    325:        FILE *mtf, *fp;
                    326:        int remote = rflag != NOSTR || rmail;
                    327:        char **t;
                    328:        char *deadletter;
                    329:        char recfile[128];
                    330: 
                    331:        /*
                    332:         * Collect user's mail from standard input.
                    333:         * Get the result as mtf.
                    334:         */
                    335: 
                    336:        pid = (pid_t)-1;
                    337:        if ((mtf = collect(hp)) == NULL)
                    338:                return;
                    339:        hp->h_seq = 1;
                    340:        if (hp->h_subject == NOSTR)
                    341:                hp->h_subject = sflag;
                    342:        if (fsize(mtf) == 0 && hp->h_subject == NOSTR) {
                    343:                printf("No message !?!\n");
                    344:                goto out;
                    345:        }
                    346:        if (intty) {
                    347:                printf("EOT\n");
                    348:                flush();
                    349:        }
                    350: 
                    351:        /*
                    352:         * Now, take the user names from the combined
                    353:         * to and cc lists and do all the alias
                    354:         * processing.
                    355:         */
                    356: 
                    357:        senderr = 0;
                    358:        to = cat(extract(hp->h_bcc, GBCC),
                    359:             cat(extract(hp->h_to, GTO),
                    360:             extract(hp->h_cc, GCC)));
                    361: /*     to = translate(outpre(elide(usermap(to))));     I can't imagine why outpre is used--adb */
                    362:        to = translate(elide(usermap(to)));
                    363:        if (!senderr)
                    364:                mapf(to, myname);
                    365:        mechk(to);
                    366:        for (gotcha = 0, np = to; np != NIL; np = np->n_flink)
                    367:                if ((np->n_type & GDEL) == 0)
                    368:                        gotcha++;
                    369:        hp->h_to = detract(to, GTO);
                    370:        hp->h_cc = detract(to, GCC);
                    371:        hp->h_bcc = detract(to, GBCC);
                    372:        if ((mtf = infix(hp, mtf)) == NULL) {
                    373:                fprintf(stderr, ". . . message lost, sorry.\n");
                    374:                return;
                    375:        }
                    376:        rewind(mtf);
                    377:        if (askme && isatty(0)) {
                    378:                char ans[64];
                    379:                puthead(hp, stdout, GTO|GCC|GBCC);
                    380:                printf("Send? [yes] ");
                    381:                if (fgets(ans, sizeof(ans), stdin) && ans[0] && tolower(ans[0]) != 'y')
                    382:                        goto dead;
                    383:        }
                    384:        if (senderr)
                    385:                goto dead;
                    386:        /*
                    387:         * Look through the recipient list for names with /'s
                    388:         * in them which we write to as files directly.
                    389:         */
                    390:        i = outof(to, mtf);
                    391:        rewind(mtf);
                    392:        if (!gotcha && !i) {
                    393:                printf("No recipients specified\n");
                    394:                goto dead;
                    395:        }
                    396:        if (senderr)
                    397:                goto dead;
                    398:        if ((gotcha - i) == 0)
                    399:                return;
                    400: 
                    401:        getrecf(rec, recfile, !!rec);
                    402:        if (recfile != NOSTR && *recfile)
                    403:                savemail(expand(recfile), hp, mtf);
                    404:        if (!gotcha)
                    405:                goto out;
                    406:        namelist = unpack(to);
                    407:        if (debug) {
                    408:                fprintf(stderr, "Recipients of message:\n");
                    409:                for (t = namelist; *t != NOSTR; t++)
                    410:                        fprintf(stderr, " \"%s\"", *t);
                    411:                fprintf(stderr, "\n");
                    412:                return;
                    413:        }
                    414: 
                    415:        /*
                    416:         * Wait, to absorb a potential zombie, then
                    417:         * fork, set up the temporary mail file as standard
                    418:         * input for "mail" and exec with the user list we generated
                    419:         * far above. Return the process id to caller in case he
                    420:         * wants to await the completion of mail.
                    421:         */
                    422: 
                    423:        wait(&s);
                    424:        rewind(mtf);
                    425:        pid = fork();
                    426:        if (pid == (pid_t)-1) {
                    427:                perror("fork");
                    428: dead:
                    429:                deadletter = Getf("DEAD");
                    430:                removefile(deadletter);                                 /* adb -- old style */
                    431:                if (fp = fopen(deadletter, "w")) {                      /* adb */
                    432:                        puthead(hp, fp, GMASK);
                    433:                        fseek(mtf, textpos, 0);
                    434:                        lcwrite(deadletter, mtf, fp);
                    435:                        fclose(fp);
                    436:                        chmod(deadletter, DEADPERM);
                    437:                } else
                    438:                        perror(deadletter);
                    439:                goto out;
                    440:        }
                    441:        if (pid == 0) {
                    442:                sigchild();
                    443: #ifdef SIGTSTP
                    444:                if (remote == 0) {
                    445:                        sigset(SIGTSTP, SIG_IGN);
                    446:                        sigset(SIGTTIN, SIG_IGN);
                    447:                        sigset(SIGTTOU, SIG_IGN);
                    448:                }
                    449: #endif
                    450:                sigignore(SIGHUP);
                    451:                sigignore(SIGINT);
                    452:                sigignore(SIGQUIT);
                    453:                s = fileno(mtf);
                    454:                for (i = 3; i < 32; i++)
                    455:                        if (i != s)
                    456:                                close(i);
                    457:                close(0);
                    458:                dup(s);
                    459:                close(s);
                    460: #ifdef CC
                    461:                submit(getpid());
                    462: #endif /* CC */
                    463:                if ((deliver = value("sendmail")) == NOSTR)
                    464:                        deliver = MAIL;
                    465:                execvp(expand(deliver), namelist);
                    466:                perror(deliver);
                    467:                exit(1);
                    468:        }
                    469: 
                    470:        if (value("sendwait")!=NOSTR)
                    471:                remote++;
                    472: out:
                    473:        if (remote) {
                    474:                while ((p = wait(&s)) != pid && p != (pid_t)-1)
                    475:                        ;
                    476:                if (s != 0)
                    477:                        senderr++;
                    478:                pid = 0;
                    479:        }
                    480:        fclose(mtf);
                    481:        return;
                    482: }
                    483: 
                    484: /*
                    485:  * Prepend a header in front of the collected stuff
                    486:  * and return the new file.
                    487:  */
                    488: 
                    489: static FILE *
                    490: infix(hp, fi)
                    491:        struct header *hp;
                    492:        FILE *fi;
                    493: {
                    494:        register FILE *nfo, *nfi;
                    495:        register int c;
                    496:        char *from, *postmark;
                    497: 
                    498:        rewind(fi);
                    499:        if ((nfo = fopen(tempMail, "w")) == NULL) {
                    500:                perror(tempMail);
                    501:                return(fi);
                    502:        }
                    503:        if ((nfi = fopen(tempMail, "r")) == NULL) {
                    504:                perror(tempMail);
                    505:                fclose(nfo);
                    506:                return(fi);
                    507:        }
                    508:        removefile(tempMail);
                    509:        postmark = value("postmark");
                    510:        from = value("from");
                    511:        if ((from != 0) || (postmark != 0)) {
                    512:                fprintf(nfo, "From: ");
                    513:                if (from)
                    514:                        fprintf(nfo, "%s@%s%s", myname, host, maildomain());
                    515:                else
                    516:                        fprintf(nfo, "%s!%s", host, myname);
                    517:                if (postmark && *postmark)
                    518:                        fprintf(nfo, " (%s)", postmark);
                    519:                putc('\n', nfo);
                    520:        }
                    521:        puthead(hp, nfo, GMASK & ~GBCC);
                    522:        textpos = ftell(nfo);
                    523:        while ((c = getc(fi)) != EOF)
                    524:                putc(c, nfo);
                    525:        if (ferror(fi)) {
                    526:                perror("read");
                    527:                return(fi);
                    528:        }
                    529:        fflush(nfo);
                    530:        if (ferror(nfo)) {
                    531:                perror(tempMail);
                    532:                fclose(nfo);
                    533:                fclose(nfi);
                    534:                return(fi);
                    535:        }
                    536:        fclose(nfo);
                    537:        fclose(fi);
                    538:        rewind(nfi);
                    539:        return(nfi);
                    540: }
                    541: 
                    542: /*
                    543:  * Dump the message header on the
                    544:  * passed file buffer.
                    545:  */
                    546: 
                    547: puthead(hp, fo, w)
                    548:        struct header *hp;
                    549:        FILE *fo;
                    550: {
                    551:        register int gotcha;
                    552: 
                    553:        gotcha = 0;
                    554:        if (hp->h_to != NOSTR && (w & GTO))
                    555:                fprintf(fo, "To: "), fmt(hp->h_to, fo), gotcha++;
                    556:        if (hp->h_cc != NOSTR && (w & GCC))
                    557:                fprintf(fo, "Cc: "), fmt(hp->h_cc, fo), gotcha++;
                    558:        if (hp->h_bcc != NOSTR && (w & GBCC))
                    559:                fprintf(fo, "Bcc: "), fmt(hp->h_bcc, fo), gotcha++;
                    560:        if (hp->h_defopt != NOSTR && (w & GDEFOPT))
                    561:                fprintf(fo, "Default-Options: %s\n", hp->h_defopt), gotcha++;
                    562:        if (w & GSUBJECT)
                    563:                if (hp->h_subject != NOSTR && *hp->h_subject)
                    564:                        fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
                    565:                else
                    566:                        if (sflag && *sflag)
                    567:                                fprintf(fo, "Subject: %s\n", sflag), gotcha++;
                    568:        if (hp->h_others != NOSTRPTR && (w & GOTHER)) {
                    569:                char **p;
                    570:                for (p = hp->h_others; *p; p++)
                    571:                        fprintf(fo, "%s\n", *p);
                    572:                gotcha++;
                    573:        }
                    574:        if (gotcha && (w & GNL))
                    575:                putc('\n', fo);
                    576:        return(0);
                    577: }
                    578: 
                    579: /*
                    580:  * Format the given text to not exceed 78 characters.
                    581:  */
                    582: static void
                    583: fmt(str, fo)
                    584:        register char *str;
                    585:        register FILE *fo;
                    586: {
                    587:        register int col = 4;
                    588:        char name[256];
                    589:        int len;
                    590: 
                    591:        str = strcpy(salloc(strlen(str)+1), str);
                    592:        while (str = yankword(str, name, 1)) {
                    593:                len = strlen(name);
                    594:                if (col > 4) {
                    595:                        if (col + len > 76) {
                    596:                                fputs(",\n    ", fo);
                    597:                                col = 4;
                    598:                        } else {
                    599:                                fputs(", ", fo);
                    600:                                col += 2;
                    601:                        }
                    602:                }
                    603:                fputs(name, fo);
                    604:                col += len;
                    605:        }
                    606:        putc('\n', fo);
                    607: }
                    608: 
                    609: /*
                    610:  * Save the outgoing mail on the passed file.
                    611:  */
                    612: static int
                    613: savemail(name, hp, fi)
                    614:        char name[];
                    615:        struct header *hp;
                    616:        FILE *fi;
                    617: {
                    618:        register FILE *fo;
                    619:        char line[BUFSIZ];
                    620:        long now;
                    621:        char *n;
                    622: 
                    623:        if (debug)
                    624:                fprintf(stderr, "save in '%s'\n", name);
                    625:        if ((fo = fopen(name, "a")) == NULL) {
                    626:                perror(name);
                    627:                return(-1);
                    628:        }
                    629:        time(&now);
                    630:        n = rflag;
                    631:        if (n == NOSTR)
                    632:                n = myname;
                    633:        fprintf(fo, "From %s %s", n, ctime(&now));
                    634:        puthead(hp, fo, GMASK);
                    635:        fseek(fi, textpos, 0);
                    636:        while (fgets(line, sizeof line, fi)) {
                    637:                if (!strncmp(line, "From ", 5))
                    638:                        putc('>', fo);
                    639:                fputs(line, fo);
                    640:        }
                    641:        putc('\n', fo);
                    642:        fflush(fo);
                    643:        if (ferror(fo))
                    644:                perror(name);
                    645:        fclose(fo);
                    646:        return(0);
                    647: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.