Annotation of researchv10no/lbin/mailx/send.c, revision 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.