Annotation of 41BSD/cmd/delivermail/deliver.c, revision 1.1

1.1     ! root        1: # include <stdio.h>
        !             2: # include <pwd.h>
        !             3: # include <signal.h>
        !             4: # include "dlvrmail.h"
        !             5: # ifdef LOG
        !             6: # include <log.h>
        !             7: # endif LOG
        !             8: 
        !             9: static char SccsId[] = "@(#)deliver.c  1.11    10/27/80";
        !            10: 
        !            11: /*
        !            12: **  DELIVER -- Deliver a message to a particular address.
        !            13: **
        !            14: **     Algorithm:
        !            15: **             Compute receiving network (i.e., mailer), host, & user.
        !            16: **             If local, see if this is really a program name.
        !            17: **             Build argument for the mailer.
        !            18: **             Create pipe through edit fcn if appropriate.
        !            19: **             Fork.
        !            20: **                     Child: call mailer
        !            21: **             Parent: call editfcn if specified.
        !            22: **             Wait for mailer to finish.
        !            23: **             Interpret exit status.
        !            24: **
        !            25: **     Parameters:
        !            26: **             to -- the address to deliver the message to.
        !            27: **             editfcn -- if non-NULL, we want to call this function
        !            28: **                     to output the letter (instead of just out-
        !            29: **                     putting it raw).
        !            30: **
        !            31: **     Returns:
        !            32: **             zero -- successfully delivered.
        !            33: **             else -- some failure, see ExitStat for more info.
        !            34: **
        !            35: **     Side Effects:
        !            36: **             The standard input is passed off to someone.
        !            37: **
        !            38: **     WARNING:
        !            39: **             The standard input is shared amongst all children,
        !            40: **             including the file pointer.  It is critical that the
        !            41: **             parent waits for the child to finish before forking
        !            42: **             another child.
        !            43: **
        !            44: **     Called By:
        !            45: **             main
        !            46: **             savemail
        !            47: **
        !            48: **     Files:
        !            49: **             standard input -- must be opened to the message to
        !            50: **                     deliver.
        !            51: */
        !            52: 
        !            53: deliver(to, editfcn)
        !            54:        addrq *to;
        !            55:        int (*editfcn)();
        !            56: {
        !            57:        register struct mailer *m;
        !            58:        char *host;
        !            59:        char *user;
        !            60:        extern struct passwd *getpwnam();
        !            61:        char **pvp;
        !            62:        extern char **buildargv();
        !            63:        auto int st;
        !            64:        register int i;
        !            65:        register char *p;
        !            66:        int pid;
        !            67:        int pvect[2];
        !            68:        extern FILE *fdopen();
        !            69:        extern int errno;
        !            70:        FILE *mfile;
        !            71:        extern putheader();
        !            72:        extern pipesig();
        !            73: 
        !            74:        /*
        !            75:        **  Compute receiving mailer, host, and to addreses.
        !            76:        **      Do some initialization first.  To is the to address
        !            77:        **      for error messages.
        !            78:        */
        !            79: 
        !            80:        To = to->q_paddr;
        !            81:        m = to->q_mailer;
        !            82:        user = to->q_user;
        !            83:        host = to->q_host;
        !            84:        Errors = 0;
        !            85:        errno = 0;
        !            86: # ifdef DEBUG
        !            87:        if (Debug)
        !            88:                printf("deliver(%s [%d, `%s', `%s'])\n", To, m, host, user);
        !            89: # endif DEBUG
        !            90: 
        !            91:        /*
        !            92:        **  Remove quote bits from user/host.
        !            93:        */
        !            94: 
        !            95:        for (p = user; (*p++ &= 0177) != '\0'; )
        !            96:                continue;
        !            97:        if (host != NULL)
        !            98:                for (p = host; (*p++ &= 0177) != '\0'; )
        !            99:                        continue;
        !           100:        
        !           101:        /*
        !           102:        **  Strip quote bits from names if the mailer wants it.
        !           103:        */
        !           104: 
        !           105:        if (flagset(M_STRIPQ, m->m_flags))
        !           106:        {
        !           107:                stripquotes(user);
        !           108:                stripquotes(host);
        !           109:        }
        !           110: 
        !           111:        /*
        !           112:        **  See if this user name is "special".
        !           113:        **      If the user is a program, diddle with the mailer spec.
        !           114:        **      If the user name has a slash in it, assume that this
        !           115:        **              is a file -- send it off without further ado.
        !           116:        **              Note that this means that editfcn's will not
        !           117:        **              be applied to the message.
        !           118:        */
        !           119: 
        !           120:        if (m == &Mailer[0])
        !           121:        {
        !           122:                if (*user == '|')
        !           123:                {
        !           124:                        user++;
        !           125:                        m = &Mailer[1];
        !           126:                }
        !           127:                else
        !           128:                {
        !           129:                        if (index(user, '/') != NULL)
        !           130:                        {
        !           131:                                i = mailfile(user);
        !           132:                                giveresponse(i, TRUE, m);
        !           133:                                return (i);
        !           134:                        }
        !           135:                }
        !           136:        }
        !           137: 
        !           138:        /*
        !           139:        **  See if the user exists.
        !           140:        **      Strictly, this is only needed to print a pretty
        !           141:        **      error message.
        !           142:        **
        !           143:        **      >>>>>>>>>> This clause assumes that the local mailer
        !           144:        **      >> NOTE >> cannot do any further aliasing; that
        !           145:        **      >>>>>>>>>> function is subsumed by delivermail.
        !           146:        */
        !           147: 
        !           148:        if (m == &Mailer[0])
        !           149:        {
        !           150:                if (getpwnam(user) == NULL)
        !           151:                {
        !           152:                        giveresponse(EX_NOUSER, TRUE, m);
        !           153:                        return (EX_NOUSER);
        !           154:                }
        !           155:        }
        !           156: 
        !           157:        /*
        !           158:        **  If the mailer wants a From line, insert a new editfcn.
        !           159:        */
        !           160: 
        !           161:        if (flagset(M_HDR, m->m_flags) && editfcn == NULL)
        !           162:                editfcn = putheader;
        !           163: 
        !           164:        /*
        !           165:        **  Call the mailer.
        !           166:        **      The argument vector gets built, pipes through 'editfcn'
        !           167:        **      are created as necessary, and we fork & exec as
        !           168:        **      appropriate.  In the parent, we call 'editfcn'.
        !           169:        */
        !           170: 
        !           171:        pvp = buildargv(m->m_argv, m->m_flags, host, user, From.q_paddr);
        !           172:        if (pvp == NULL)
        !           173:        {
        !           174:                usrerr("name too long");
        !           175:                return (-1);
        !           176:        }
        !           177:        rewind(stdin);
        !           178: 
        !           179:        /* create a pipe if we will need one */
        !           180:        if (editfcn != NULL && pipe(pvect) < 0)
        !           181:        {
        !           182:                syserr("pipe");
        !           183:                return (-1);
        !           184:        }
        !           185: # ifdef VFORK
        !           186:        pid = vfork();
        !           187: # else
        !           188:        pid = fork();
        !           189: # endif
        !           190:        if (pid < 0)
        !           191:        {
        !           192:                syserr("Cannot fork");
        !           193:                if (editfcn != NULL)
        !           194:                {
        !           195:                        close(pvect[0]);
        !           196:                        close(pvect[1]);
        !           197:                }
        !           198:                return (-1);
        !           199:        }
        !           200:        else if (pid == 0)
        !           201:        {
        !           202:                /* child -- set up input & exec mailer */
        !           203:                /* make diagnostic output be standard output */
        !           204:                close(2);
        !           205:                dup(1);
        !           206:                signal(SIGINT, SIG_IGN);
        !           207:                if (editfcn != NULL)
        !           208:                {
        !           209:                        close(0);
        !           210:                        if (dup(pvect[0]) < 0)
        !           211:                        {
        !           212:                                syserr("Cannot dup to zero!");
        !           213:                                _exit(EX_OSERR);
        !           214:                        }
        !           215:                        close(pvect[0]);
        !           216:                        close(pvect[1]);
        !           217:                }
        !           218:                if (!flagset(M_RESTR, m->m_flags))
        !           219:                        setuid(getuid());
        !           220: # ifdef LOG
        !           221:                initlog(NULL, 0, LOG_CLOSE);
        !           222: # endif LOG
        !           223: # ifndef VFORK
        !           224:                /*
        !           225:                 * We have to be careful with vfork - we can't mung up the
        !           226:                 * memory but we don't want the mailer to inherit any extra
        !           227:                 * open files.  Chances are the mailer won't
        !           228:                 * care about an extra file, but then again you never know.
        !           229:                 * Actually, we would like to close(fileno(pwf)), but it's
        !           230:                 * declared static so we can't.  But if we fclose(pwf), which
        !           231:                 * is what endpwent does, it closes it in the parent too and
        !           232:                 * the next getpwnam will be slower.  If you have a weird mailer
        !           233:                 * that chokes on the extra file you should do the endpwent().
        !           234:                 */
        !           235:                endpwent();
        !           236: # endif
        !           237:                execv(m->m_mailer, pvp);
        !           238:                /* syserr fails because log is closed */
        !           239:                /* syserr("Cannot exec %s", m->m_mailer); */
        !           240:                _exit(EX_UNAVAILABLE);
        !           241:        }
        !           242: 
        !           243:        /* arrange to write out header message if error */
        !           244:        if (editfcn != NULL)
        !           245:        {
        !           246:                close(pvect[0]);
        !           247:                signal(SIGPIPE, pipesig);
        !           248:                mfile = fdopen(pvect[1], "w");
        !           249:                (*editfcn)(mfile);
        !           250:                fclose(mfile);
        !           251:        }
        !           252: 
        !           253:        /*
        !           254:        **  Wait for child to die and report status.
        !           255:        **      We should never get fatal errors (e.g., segmentation
        !           256:        **      violation), so we report those specially.  For other
        !           257:        **      errors, we choose a status message (into statmsg),
        !           258:        **      and if it represents an error, we print it.
        !           259:        */
        !           260: 
        !           261:        while ((i = wait(&st)) > 0 && i != pid)
        !           262:                continue;
        !           263:        if (i < 0)
        !           264:        {
        !           265:                syserr("wait");
        !           266:                return (-1);
        !           267:        }
        !           268:        if ((st & 0377) != 0)
        !           269:        {
        !           270:                syserr("%s: stat %o", pvp[0], st);
        !           271:                ExitStat = EX_UNAVAILABLE;
        !           272:                return (-1);
        !           273:        }
        !           274:        i = (st >> 8) & 0377;
        !           275:        giveresponse(i, FALSE, m);
        !           276:        return (i);
        !           277: }
        !           278: /*
        !           279: **  GIVERESPONSE -- Interpret an error response from a mailer
        !           280: **
        !           281: **     Parameters:
        !           282: **             stat -- the status code from the mailer (high byte
        !           283: **                     only; core dumps must have been taken care of
        !           284: **                     already).
        !           285: **             force -- if set, force an error message output, even
        !           286: **                     if the mailer seems to like to print its own
        !           287: **                     messages.
        !           288: **             m -- the mailer descriptor for this mailer.
        !           289: **
        !           290: **     Returns:
        !           291: **             none.
        !           292: **
        !           293: **     Side Effects:
        !           294: **             Errors may be incremented.
        !           295: **             ExitStat may be set.
        !           296: **
        !           297: **     Called By:
        !           298: **             deliver
        !           299: */
        !           300: 
        !           301: giveresponse(stat, force, m)
        !           302:        int stat;
        !           303:        int force;
        !           304:        register struct mailer *m;
        !           305: {
        !           306:        register char *statmsg;
        !           307:        extern char *SysExMsg[];
        !           308:        register int i;
        !           309:        extern int N_SysEx;
        !           310:        extern long MsgSize;
        !           311:        char buf[30];
        !           312: 
        !           313:        i = stat - EX__BASE;
        !           314:        if (i < 0 || i > N_SysEx)
        !           315:                statmsg = NULL;
        !           316:        else
        !           317:                statmsg = SysExMsg[i];
        !           318:        if (stat == 0)
        !           319:                statmsg = "ok";
        !           320:        else
        !           321:        {
        !           322:                Errors++;
        !           323:                if (statmsg == NULL && m->m_badstat != 0)
        !           324:                {
        !           325:                        stat = m->m_badstat;
        !           326:                        i = stat - EX__BASE;
        !           327: # ifdef DEBUG
        !           328:                        if (i < 0 || i >= N_SysEx)
        !           329:                                syserr("Bad m_badstat %d", stat);
        !           330:                        else
        !           331: # endif DEBUG
        !           332:                        statmsg = SysExMsg[i];
        !           333:                }
        !           334:                if (statmsg == NULL)
        !           335:                        usrerr("unknown mailer response %d", stat);
        !           336:                else if (force || !flagset(M_QUIET, m->m_flags))
        !           337:                        usrerr("%s", statmsg);
        !           338:        }
        !           339: 
        !           340:        /*
        !           341:        **  Final cleanup.
        !           342:        **      Log a record of the transaction.  Compute the new
        !           343:        **      ExitStat -- if we already had an error, stick with
        !           344:        **      that.
        !           345:        */
        !           346: 
        !           347:        if (statmsg == NULL)
        !           348:        {
        !           349:                sprintf(buf, "error %d", stat);
        !           350:                statmsg = buf;
        !           351:        }
        !           352: 
        !           353: # ifdef LOG
        !           354:        logmsg(LOG_INFO, "%s->%s: %ld: %s", From.q_paddr, To, MsgSize, statmsg);
        !           355: # endif LOG
        !           356:        setstat(stat);
        !           357:        return (stat);
        !           358: }
        !           359: /*
        !           360: **  PUTHEADER -- insert the From header into some mail
        !           361: **
        !           362: **     For mailers such as 'msgs' that want the header inserted
        !           363: **     into the mail, this edit filter inserts the From line and
        !           364: **     then passes the rest of the message through.
        !           365: **
        !           366: **     Parameters:
        !           367: **             fp -- the file pointer for the output.
        !           368: **
        !           369: **     Returns:
        !           370: **             none
        !           371: **
        !           372: **     Side Effects:
        !           373: **             Puts a "From" line in UNIX format, and then
        !           374: **                     outputs the rest of the message.
        !           375: **
        !           376: **     Called By:
        !           377: **             deliver
        !           378: */
        !           379: 
        !           380: putheader(fp)
        !           381:        register FILE *fp;
        !           382: {
        !           383:        char buf[MAXLINE + 1];
        !           384:        long tim;
        !           385:        extern char *ctime();
        !           386: 
        !           387:        time(&tim);
        !           388:        fprintf(fp, "From %s %s", From.q_paddr, ctime(&tim));
        !           389:        while (fgets(buf, sizeof buf, stdin) != NULL && !ferror(fp))
        !           390:                fputs(buf, fp);
        !           391:        if (ferror(fp))
        !           392:        {
        !           393:                syserr("putheader: write error");
        !           394:                setstat(EX_IOERR);
        !           395:        }
        !           396: }
        !           397: /*
        !           398: **  PIPESIG -- Handle broken pipe signals
        !           399: **
        !           400: **     This just logs an error.
        !           401: **
        !           402: **     Parameters:
        !           403: **             none
        !           404: **
        !           405: **     Returns:
        !           406: **             none
        !           407: **
        !           408: **     Side Effects:
        !           409: **             logs an error message.
        !           410: */
        !           411: 
        !           412: pipesig()
        !           413: {
        !           414:        syserr("Broken pipe");
        !           415:        signal(SIGPIPE, SIG_IGN);
        !           416: }
        !           417: /*
        !           418: **  SENDTO -- Designate a send list.
        !           419: **
        !           420: **     The parameter is a comma-separated list of people to send to.
        !           421: **     This routine arranges to send to all of them.
        !           422: **
        !           423: **     Parameters:
        !           424: **             list -- the send list.
        !           425: **             copyf -- the copy flag; passed to parse.
        !           426: **
        !           427: **     Returns:
        !           428: **             none
        !           429: **
        !           430: **     Side Effects:
        !           431: **             none.
        !           432: **
        !           433: **     Called By:
        !           434: **             main
        !           435: **             alias
        !           436: */
        !           437: 
        !           438: sendto(list, copyf)
        !           439:        char *list;
        !           440:        int copyf;
        !           441: {
        !           442:        register char *p;
        !           443:        register char *q;
        !           444:        register char c;
        !           445:        addrq *a;
        !           446:        extern addrq *parse();
        !           447:        bool more;
        !           448: 
        !           449:        /* more keeps track of what the previous delimiter was */
        !           450:        more = TRUE;
        !           451:        for (p = list; more; )
        !           452:        {
        !           453:                /* find the end of this address */
        !           454:                q = p;
        !           455:                while ((c = *p++) != '\0' && c != ',' && c != '\n')
        !           456:                        continue;
        !           457:                more = c != '\0';
        !           458:                *--p = '\0';
        !           459:                if (more)
        !           460:                        p++;
        !           461: 
        !           462:                /* parse the address */
        !           463:                if ((a = parse(q, (addrq *) NULL, copyf)) == NULL)
        !           464:                        continue;
        !           465: 
        !           466:                /* arrange to send to this person */
        !           467:                recipient(a, &SendQ);
        !           468:        }
        !           469:        To = NULL;
        !           470: }
        !           471: /*
        !           472: **  RECIPIENT -- Designate a message recipient
        !           473: **
        !           474: **     Saves the named person for future mailing.
        !           475: **
        !           476: **     Designates a person as a recipient.  This routine
        !           477: **     does the initial parsing, and checks to see if
        !           478: **     this person has already received the mail.
        !           479: **     It also supresses local network names and turns them into
        !           480: **     local names.
        !           481: **
        !           482: **     Parameters:
        !           483: **             a -- the (preparsed) address header for the recipient.
        !           484: **             targetq -- the queue to add the name to.
        !           485: **
        !           486: **     Returns:
        !           487: **             none.
        !           488: **
        !           489: **     Side Effects:
        !           490: **             none.
        !           491: **
        !           492: **     Called By:
        !           493: **             sendto
        !           494: **             main
        !           495: */
        !           496: 
        !           497: recipient(a, targetq)
        !           498:        register addrq *a;
        !           499:        addrq *targetq;
        !           500: {
        !           501:        register addrq *q;
        !           502:        register struct mailer *m;
        !           503:        register char **pvp;
        !           504:        extern char *xalloc();
        !           505:        extern bool forward();
        !           506:        extern int errno;
        !           507:        extern bool sameaddr();
        !           508: 
        !           509:        To = a->q_paddr;
        !           510:        m = a->q_mailer;
        !           511:        errno = 0;
        !           512: # ifdef DEBUG
        !           513:        if (Debug)
        !           514:                printf("recipient(%s)\n", To);
        !           515: # endif DEBUG
        !           516: 
        !           517:        /*
        !           518:        **  Look up this person in the recipient list.  If they
        !           519:        **  are there already, return, otherwise continue.
        !           520:        */
        !           521: 
        !           522:        if (!ForceMail)
        !           523:        {
        !           524:                for (q = &SendQ; (q = nxtinq(q)) != NULL; )
        !           525:                        if (sameaddr(q, a, FALSE))
        !           526:                        {
        !           527: # ifdef DEBUG
        !           528:                                if (Debug)
        !           529:                                        printf("(%s in SendQ)\n", a->q_paddr);
        !           530: # endif DEBUG
        !           531:                                return;
        !           532:                        }
        !           533:                for (q = &AliasQ; (q = nxtinq(q)) != NULL; )
        !           534:                        if (sameaddr(q, a, FALSE))
        !           535:                        {
        !           536: # ifdef DEBUG
        !           537:                                if (Debug)
        !           538:                                        printf("(%s in AliasQ)\n", a->q_paddr);
        !           539: # endif DEBUG
        !           540:                                return;
        !           541:                        }
        !           542:        }
        !           543: 
        !           544:        /*
        !           545:        **  See if the user wants hir mail forwarded.
        !           546:        **      `Forward' must do the forwarding recursively.
        !           547:        */
        !           548: 
        !           549:        if (m == &Mailer[0] && !NoAlias && targetq == &SendQ && forward(a))
        !           550:                return;
        !           551: 
        !           552:        /*
        !           553:        **  Put the user onto the target queue.
        !           554:        */
        !           555: 
        !           556:        if (targetq != NULL)
        !           557:        {
        !           558:                putonq(a, targetq);
        !           559:        }
        !           560: 
        !           561:        return;
        !           562: }
        !           563: /*
        !           564: **  BUILDARGV -- Build an argument vector for a mail server.
        !           565: **
        !           566: **     Using a template defined in config.c, an argv is built.
        !           567: **     The format of the template is already a vector.  The
        !           568: **     items of this vector are copied, unless a dollar sign
        !           569: **     is encountered.  In this case, the next character
        !           570: **     specifies something else to copy in.  These can be
        !           571: **             $f      The from address.
        !           572: **             $h      The host.
        !           573: **             $u      The user.
        !           574: **             $c      The hop count.
        !           575: **     The vector is built in a local buffer.  A pointer to
        !           576: **     the static argv is returned.
        !           577: **
        !           578: **     Parameters:
        !           579: **             tmplt -- a template for an argument vector.
        !           580: **             flags -- the flags for this server.
        !           581: **             host -- the host name to send to.
        !           582: **             user -- the user name to send to.
        !           583: **             from -- the person this mail is from.
        !           584: **
        !           585: **     Returns:
        !           586: **             A pointer to an argv.
        !           587: **
        !           588: **     Side Effects:
        !           589: **             none
        !           590: **
        !           591: **     WARNING:
        !           592: **             Since the argv is staticly allocated, any subsequent
        !           593: **             calls will clobber the old argv.
        !           594: **
        !           595: **     Called By:
        !           596: **             deliver
        !           597: */
        !           598: 
        !           599: char **
        !           600: buildargv(tmplt, flags, host, user, from)
        !           601:        char **tmplt;
        !           602:        int flags;
        !           603:        char *host;
        !           604:        char *user;
        !           605:        char *from;
        !           606: {
        !           607:        register char *p;
        !           608:        register char *q;
        !           609:        static char *pv[MAXPV+1];
        !           610:        char **pvp;
        !           611:        char **mvp;
        !           612:        static char buf[512];
        !           613:        register char *bp;
        !           614:        char pbuf[30];
        !           615: 
        !           616:        /*
        !           617:        **  Do initial argv setup.
        !           618:        **      Insert the mailer name.  Notice that $x expansion is
        !           619:        **      NOT done on the mailer name.  Then, if the mailer has
        !           620:        **      a picky -f flag, we insert it as appropriate.  This
        !           621:        **      code does not check for 'pv' overflow; this places a
        !           622:        **      manifest lower limit of 4 for MAXPV.
        !           623:        */
        !           624: 
        !           625:        pvp = pv;
        !           626:        bp = buf;
        !           627: 
        !           628:        *pvp++ = tmplt[0];
        !           629: 
        !           630:        /* insert -f or -r flag as appropriate */
        !           631:        if (flagset(M_FOPT|M_ROPT, flags) && FromFlag)
        !           632:        {
        !           633:                if (flagset(M_FOPT, flags))
        !           634:                        *pvp++ = "-f";
        !           635:                else
        !           636:                        *pvp++ = "-r";
        !           637:                *pvp++ = From.q_paddr;
        !           638:        }
        !           639: 
        !           640:        /*
        !           641:        **  Build the rest of argv.
        !           642:        **      For each prototype parameter, the prototype is
        !           643:        **      scanned character at a time.  If a dollar-sign is
        !           644:        **      found, 'q' is set to the appropriate expansion,
        !           645:        **      otherwise it is null.  Then either the string
        !           646:        **      pointed to by q, or the original character, is
        !           647:        **      interpolated into the buffer.  Buffer overflow is
        !           648:        **      checked.
        !           649:        */
        !           650: 
        !           651:        for (mvp = tmplt; (p = *++mvp) != NULL; )
        !           652:        {
        !           653:                if (pvp >= &pv[MAXPV])
        !           654:                {
        !           655:                        syserr("Too many parameters to %s", pv[0]);
        !           656:                        return (NULL);
        !           657:                }
        !           658:                *pvp++ = bp;
        !           659:                for (; *p != '\0'; p++)
        !           660:                {
        !           661:                        /* q will be the interpolated quantity */
        !           662:                        q = NULL;
        !           663:                        if (*p == '$')
        !           664:                        {
        !           665:                                switch (*++p)
        !           666:                                {
        !           667:                                  case 'f':     /* from person */
        !           668:                                        q = from;
        !           669:                                        break;
        !           670: 
        !           671:                                  case 'u':     /* user */
        !           672:                                        q = user;
        !           673:                                        break;
        !           674: 
        !           675:                                  case 'h':     /* host */
        !           676:                                        q = host;
        !           677:                                        break;
        !           678: 
        !           679:                                  case 'c':     /* hop count */
        !           680:                                        sprintf(pbuf, "%d", HopCount);
        !           681:                                        q = pbuf;
        !           682:                                        break;
        !           683:                                }
        !           684:                        }
        !           685: 
        !           686:                        /*
        !           687:                        **  Interpolate q or output one character
        !           688:                        **      Strip quote bits as we proceed.....
        !           689:                        */
        !           690: 
        !           691:                        if (q != NULL)
        !           692:                        {
        !           693:                                while (bp < &buf[sizeof buf - 1] && (*bp++ = *q++) != '\0')
        !           694:                                        continue;
        !           695:                                bp--;
        !           696:                        }
        !           697:                        else if (bp < &buf[sizeof buf - 1])
        !           698:                                *bp++ = *p;
        !           699:                }
        !           700:                *bp++ = '\0';
        !           701:                if (bp >= &buf[sizeof buf - 1])
        !           702:                        return (NULL);
        !           703:        }
        !           704:        *pvp = NULL;
        !           705: 
        !           706: # ifdef DEBUG
        !           707:        if (Debug)
        !           708:        {
        !           709:                printf("Interpolated argv is:\n");
        !           710:                for (mvp = pv; *mvp != NULL; mvp++)
        !           711:                        printf("\t%s\n", *mvp);
        !           712:        }
        !           713: # endif DEBUG
        !           714: 
        !           715:        return (pv);
        !           716: }
        !           717: /*
        !           718: **  MAILFILE -- Send a message to a file.
        !           719: **
        !           720: **     Parameters:
        !           721: **             filename -- the name of the file to send to.
        !           722: **
        !           723: **     Returns:
        !           724: **             The exit code associated with the operation.
        !           725: **
        !           726: **     Side Effects:
        !           727: **             none.
        !           728: **
        !           729: **     Called By:
        !           730: **             deliver
        !           731: */
        !           732: 
        !           733: mailfile(filename)
        !           734:        char *filename;
        !           735: {
        !           736:        char buf[MAXLINE];
        !           737:        register FILE *f;
        !           738:        auto long tim;
        !           739:        extern char *ctime();
        !           740: 
        !           741:        f = fopen(filename, "a");
        !           742:        if (f == NULL)
        !           743:                return (EX_CANTCREAT);
        !           744:        
        !           745:        /* output the timestamp */
        !           746:        time(&tim);
        !           747:        fprintf(f, "From %s %s", From.q_paddr, ctime(&tim));
        !           748:        rewind(stdin);
        !           749:        while (fgets(buf, sizeof buf, stdin) != NULL)
        !           750:        {
        !           751:                fputs(buf, f);
        !           752:                if (ferror(f))
        !           753:                {
        !           754:                        fclose(f);
        !           755:                        return (EX_IOERR);
        !           756:                }
        !           757:        }
        !           758:        fputs("\n", f);
        !           759:        fclose(f);
        !           760:        return (EX_OK);
        !           761: }

unix.superglobalmegacorp.com

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