Annotation of researchv10no/cmd/nupas/send/main.c, revision 1.1

1.1     ! root        1: #include <stdio.h>
        !             2: #include <regexp.h>
        !             3: #include <signal.h>
        !             4: #include "mail.h"
        !             5: #include "string.h"
        !             6: #include "message.h"
        !             7: #include "dest.h"
        !             8: #include "aux.h"
        !             9: #include "process.h"
        !            10: 
        !            11: /* globals to all files */
        !            12: int rmail = 0;
        !            13: int onatty = 0;
        !            14: char *thissys;
        !            15: int nflg = 0;
        !            16: int debug = 0;
        !            17: 
        !            18: /* global to this file */
        !            19: static string *errstr;
        !            20: static message *mp;
        !            21: static int interrupt;
        !            22: static char stderrbuf[BUFSIZ];
        !            23: static int savemail;
        !            24: 
        !            25: /* imports (other than in .h's) */
        !            26: extern int nsysfile;
        !            27: extern void exit();
        !            28: extern FILE* lockopen();
        !            29: 
        !            30: /* interrupt handling */
        !            31: SIGRETURN
        !            32: catch_int(s)
        !            33:        int s;
        !            34: {
        !            35:        signal(SIGINT, catch_int);
        !            36:        interrupt = 1;
        !            37: }
        !            38: 
        !            39: /* save the mail and go away */
        !            40: SIGRETURN
        !            41: save_on_int(s)
        !            42:        int s;
        !            43: {
        !            44:        cleanlocks();
        !            45:        save_mail(mp);
        !            46:        exit(1);
        !            47: }
        !            48: 
        !            49: /* save the mail and go away */
        !            50: SIGRETURN
        !            51: die_on_quit(s)
        !            52:        int s;
        !            53: {
        !            54:        cleanlocks();
        !            55:        exit(1);
        !            56: }
        !            57: 
        !            58: main(ac, av)
        !            59:        int ac;
        !            60:        char *av[];
        !            61: {
        !            62:        int i,j;
        !            63:        dest *dp=NULL;
        !            64:        int checkforward;
        !            65:        SIG_TYP fint, fquit, fhup;
        !            66:        char *base;
        !            67:        int rv;
        !            68: 
        !            69:        /* process args */
        !            70:        setbuf(stderr, stderrbuf);
        !            71:        for (i = 1; i < ac; i++) {
        !            72:                if (av[i][0] == '-') {
        !            73:                        for(j=1; av[i][j]; j++)
        !            74:                                /* option */
        !            75:                                switch (av[i][1]) {
        !            76:                                case '#':
        !            77:                                        nflg = 1;
        !            78:                                        break;
        !            79:                                case 'd':
        !            80:                                        debug = 1;
        !            81:                                        break;
        !            82:                                default:
        !            83:                                        fprintf(stderr, "usage: mail [-#] list-of-addresses\n");
        !            84:                                        exit(1);
        !            85:                                }
        !            86:                } else
        !            87:                        /* destination */
        !            88:                        d_insert(&dp, d_new(s_copy(av[i])));
        !            89:        }
        !            90:        if (dp == NULL) {
        !            91:                fprintf(stderr, "usage: mail [-#] address-list\n");
        !            92:                exit(1);
        !            93:        }
        !            94: 
        !            95:        /*
        !            96:         * get context:
        !            97:         *      - whether we're rmail or mail
        !            98:         *      - whether on a tty
        !            99:         */
        !           100:        base = basename(av[0]);
        !           101:        checkforward = rmail = strcmp(base, "rmail")==0;
        !           102:        onatty = (!rmail) && isatty(0);
        !           103:        thissys = sysname_read();
        !           104:        if (!nflg) {
        !           105:                if ((fint=signal(SIGINT, SIG_IGN))!=SIG_DFL)
        !           106:                        signal(SIGINT, fint);
        !           107:                else
        !           108:                        signal(SIGINT, fint = (SIG_TYP)catch_int);
        !           109:                if ((fquit=signal(SIGQUIT, SIG_IGN))!=SIG_DFL)
        !           110:                        signal(SIGQUIT, fquit);
        !           111:                else
        !           112:                        signal(SIGQUIT, die_on_quit);
        !           113:                if ((fhup=signal(SIGHUP, SIG_IGN))!=SIG_DFL)
        !           114:                        signal(SIGHUP, fhup);
        !           115:                else
        !           116:                        signal(SIGHUP, fhup = (SIG_TYP)catch_int);
        !           117: 
        !           118:                mp = m_read(stdin, rmail, onatty);
        !           119:                if (mp == NULL)
        !           120:                        exit(0);
        !           121:                if (interrupt != 0) {
        !           122:                        save_mail(mp);
        !           123:                        exit(1);
        !           124:                }
        !           125: 
        !           126:                if (fint==(SIG_TYP)catch_int)
        !           127:                        signal(SIGINT, save_on_int);
        !           128:                if (fhup==(SIG_TYP)catch_int)
        !           129:                        signal(SIGHUP, save_on_int);
        !           130:        } else {
        !           131:                mp = m_new();
        !           132:                default_from(mp);
        !           133:        }
        !           134:        errstr = s_new();
        !           135:        (void)getrules();
        !           136: 
        !           137:        /*
        !           138:         *  If this is a gateway, translate the sender address into a local
        !           139:         *  address.  This only happens if mail to the local address is 
        !           140:         *  forwarded to the sender.
        !           141:         */
        !           142:        gateway(mp);
        !           143: 
        !           144:        /*
        !           145:         *  Protect against shell characters in the sender name for
        !           146:         *  security reasons.
        !           147:         */
        !           148:        s_restart(mp->sender);
        !           149:        if (shellchars(s_to_c(mp->sender)))
        !           150:                mp->replyaddr = s_copy("postmaster");
        !           151:        else
        !           152:                mp->replyaddr = s_clone(mp->sender);
        !           153:        s_restart(mp->replyaddr);
        !           154: 
        !           155:        /*
        !           156:         *  reject messages that are too long.  We don't do it earlier
        !           157:         *  in m_read since we haven't set up enough things yet.
        !           158:         */
        !           159:        if(mp->size < 0)
        !           160:                return refuse(dp, mp, "message too long", 0);
        !           161: 
        !           162:        rv = send(dp, mp, checkforward);
        !           163:        if(savemail)
        !           164:                save_mail(mp);
        !           165:        return rv;
        !           166: }
        !           167: 
        !           168: 
        !           169: /* send a message to a list of sites */
        !           170: send(destp, mp, checkforward)
        !           171:        dest *destp;
        !           172:        message *mp;
        !           173: {
        !           174:        dest *dp;               /* destination being acted upon */
        !           175:        dest *bound;            /* bound destinations */
        !           176:        int errors=0;
        !           177:        static int forked;
        !           178:        extern dest *up_bind();
        !           179: 
        !           180:        /* bind the destinations to actions */
        !           181:        bound = up_bind(destp, mp, checkforward);
        !           182: 
        !           183:        /* loop through and execute commands */
        !           184:        for (dp = d_rm(&bound); dp != NULL; dp = d_rm(&bound)) {
        !           185:                switch (dp->status) {
        !           186:                case d_cat:
        !           187:                        errors += cat_mail(dp, mp);
        !           188:                        break;
        !           189:                case d_pipeto:
        !           190:                case d_pipe:
        !           191:                        if (!rmail && !nflg && !forked) {
        !           192:                                forked = 1;
        !           193:                                lesstedious();
        !           194:                        }
        !           195:                        errors += pipe_mail(dp, mp, dp->status==d_pipeto);
        !           196:                        break;
        !           197:                default:
        !           198:                        errors += complain_mail(dp, mp);
        !           199:                        break;
        !           200:                }
        !           201:        }
        !           202: 
        !           203:        return errors;
        !           204: }
        !           205: 
        !           206: /* avoid user tedium (as Mike Lesk said in a previous version) */
        !           207: lesstedious()
        !           208: {
        !           209:        int i;
        !           210: 
        !           211:        switch(fork()){
        !           212:        case -1:
        !           213:                onatty = 0;
        !           214:                break;
        !           215:        case 0:
        !           216:                signal(SIGHUP, SIG_IGN);
        !           217:                signal(SIGINT, SIG_IGN);
        !           218:                signal(SIGQUIT, SIG_IGN);
        !           219:                signal(SIGTERM, SIG_IGN);
        !           220:                setpgrp(getpid());
        !           221:                for(i=0; i<nsysfile; i++)
        !           222:                        close(i);
        !           223:                onatty = 0;
        !           224:                savemail=0;
        !           225:                break;
        !           226:        default:
        !           227:                exit(0);
        !           228:        }
        !           229: }
        !           230: 
        !           231: 
        !           232: /* save the mail */
        !           233: save_mail(mp)
        !           234:        message *mp;
        !           235: {
        !           236:        FILE *fp;
        !           237:        string *file=s_new();
        !           238:        char *home;
        !           239:        static saved = 0;
        !           240:        int uid, gid;
        !           241:        extern char *getenv();
        !           242: 
        !           243:        setuid(uid=getuid());
        !           244:        setgid(gid=getgid());
        !           245:        if ((home = getenv("HOME")) == NULL)
        !           246:                return;
        !           247:        s_append(file, home);
        !           248:        s_append(file, "/dead.letter");
        !           249:        if ((fp = lockopen(s_to_c(file), "w", MBOXMODE, uid, gid)) == NULL)
        !           250:                return;
        !           251:        m_bprint(mp, fp);
        !           252:        lockclose(fp);
        !           253:        fprintf(stderr, "saved in %s\n", s_to_c(file));
        !           254: }
        !           255: 
        !           256: /* remember the interrupt happened */
        !           257: /* dispose of incorrect addresses */
        !           258: complain_mail(dp, mp)
        !           259:        dest *dp;
        !           260:        message *mp;
        !           261: {
        !           262:        char *msg;
        !           263: 
        !           264:        switch (dp->status) {
        !           265:        case d_undefined:
        !           266:                msg = "Invalid address"; /* a little different, for debugging */
        !           267:                break;
        !           268:        case d_syntax:
        !           269:                msg = "invalid address";
        !           270:                break;
        !           271:        case d_unknown:
        !           272:                msg = "unknown user";
        !           273:                break;
        !           274:        case d_eloop:
        !           275:        case d_loop:
        !           276:                msg = "forwarding loop";
        !           277:                break;
        !           278:        case d_noforward:
        !           279:                if(dp->pstat && *s_to_c(dp->repl2))
        !           280:                        return refuse(dp, mp, s_to_c(dp->repl2), dp->pstat);
        !           281:                else
        !           282:                        msg = "destination unknown or forwarding disallowed";
        !           283:                break;
        !           284:        case d_pipe:
        !           285:                msg = "broken pipe";
        !           286:                break;
        !           287:        case d_cat:
        !           288:                msg = "broken cat";
        !           289:                break;
        !           290:        case d_translate:
        !           291:                if(dp->pstat && *s_to_c(dp->repl2))
        !           292:                        return refuse(dp, mp, s_to_c(dp->repl2), dp->pstat);
        !           293:                else
        !           294:                        msg = "name translation failed";
        !           295:                break;
        !           296:        case d_alias:
        !           297:                msg = "broken alias";
        !           298:                break;
        !           299:        case d_badmbox:
        !           300:                msg = "corrupted mailbox";
        !           301:                break;
        !           302:        case d_resource:
        !           303:                msg = "out of some resource.  Try again later.";
        !           304:                break;
        !           305:        }
        !           306:        if (nflg) {
        !           307:                printf("%s: %s\n", msg, s_to_c(dp->addr));
        !           308:                return 0;
        !           309:        }
        !           310:        return refuse(dp, mp, msg, 0);
        !           311: }
        !           312: 
        !           313: /* dispose of remote addresses */
        !           314: pipe_mail(dp, mp, dolock)
        !           315:        dest *dp;
        !           316:        message *mp;
        !           317:        int dolock;
        !           318: {
        !           319:        string *file;
        !           320:        FILE *fp;
        !           321:        dest *next, *list=NULL;
        !           322:        string *cmd;
        !           323:        process *pp;
        !           324:        int status;
        !           325:        string *errstr=s_new();
        !           326: 
        !           327:        /*
        !           328:         *  collect the arguments
        !           329:         */
        !           330:        file = s_new();
        !           331:        abspath(s_to_c(dp->addr), MAILROOT, file);
        !           332:        next = d_rm_same(&dp);
        !           333:        cmd = s_clone(s_restart(next->repl1));
        !           334:        for(; next != NULL; next = d_rm_same(&dp)) {
        !           335:                if ((next->uid!=-1 || next->gid !=-1)
        !           336:                && shellchars(s_to_c(next->addr))){
        !           337:                        /* this could be a serious security violation */
        !           338:                        next->status=d_syntax;
        !           339:                        complain_mail(next, mp);
        !           340:                        continue;
        !           341:                }
        !           342:                if (next->repl2 != NULL) {
        !           343:                        s_append(cmd, " ");
        !           344:                        s_append(cmd, s_to_c(next->repl2));
        !           345:                }
        !           346:                d_insert(&list, next);
        !           347:        }
        !           348: 
        !           349:        if (nflg) {
        !           350:                puts(s_to_c(cmd));
        !           351:                s_free(cmd);
        !           352:                s_free(file);
        !           353:                return 0;
        !           354:        }
        !           355: 
        !           356:        /*
        !           357:         *  lock the mailbox (so that `Pipe to's run sequentially)
        !           358:         */
        !           359:        if(dolock)
        !           360:                fp = lockopen(s_to_c(file), "r", 0, 0, 0);
        !           361:        else
        !           362:                fp = NULL;
        !           363:        s_free(file);
        !           364: 
        !           365:        /*
        !           366:         *  run the process
        !           367:         */
        !           368:        pp = proc_start(s_to_c(cmd), instream(), (stream *)NULL,
        !           369:                        outstream(), list->uid);
        !           370:        if(pp==NULL || pp->std[0]==NULL || pp->std[2]==NULL)
        !           371:                return refuse(list, mp, "out of processes, pipes, or memory", 0);
        !           372:        m_print(mp, pp->std[0]->fp, thissys, 0);
        !           373:        stream_free(pp->std[0]); pp->std[0] = NULL;
        !           374:        while(s_read_line(pp->std[2]->fp, errstr) != NULL)
        !           375:                ;
        !           376:        status = proc_wait(pp);
        !           377:        proc_free(pp);
        !           378:        s_free(cmd);
        !           379: 
        !           380:        /*
        !           381:         *  unlock the mailbox (if it was locked)
        !           382:         */
        !           383:        if(fp!=NULL)
        !           384:                lockclose(fp);
        !           385: 
        !           386:        /*
        !           387:         *  return status
        !           388:         */
        !           389:        if (status != 0)
        !           390:                return refuse(list, mp, s_to_c(errstr), status);
        !           391:        loglist(list, mp, "remote");
        !           392:        return 0;
        !           393: }
        !           394: 
        !           395: /* dispose of local addresses */
        !           396: cat_mail(dp, mp)
        !           397:        dest *dp;
        !           398:        message *mp;
        !           399: {
        !           400:        FILE *fp;
        !           401:        char *rcvr;
        !           402: 
        !           403:        if (nflg) {
        !           404:                printf("cat >> %s\n", s_to_c(dp->repl1));
        !           405:                return 0;
        !           406:        }
        !           407:        fp=lockopen(s_to_c(dp->repl1), "a", MBOXMODE, dp->uid, dp->gid);
        !           408:        if (fp == NULL)
        !           409:                return refuse(dp, mp, "mail file cannot be opened", 0);
        !           410:        m_print(mp, fp, (char *)NULL, 1);
        !           411:        fputs("\n", fp);
        !           412:        fflush(fp);
        !           413:        if (ferror(fp)) {
        !           414:                lockclose(fp);
        !           415:                return refuse(dp, mp, "error writing mail file", 0);
        !           416:        }
        !           417:        lockclose(fp);
        !           418:        rcvr = basename(s_to_c(dp->repl1));
        !           419:        logdelivery(dp, rcvr, mp);
        !           420:        notify(rcvr, mp);
        !           421:        return 0;
        !           422: }
        !           423: 
        !           424: static void
        !           425: appaddr(sp, dp)
        !           426:        string *sp;
        !           427:        dest *dp;
        !           428: {
        !           429:        dest *parent;
        !           430: 
        !           431:        if (dp->parent != NULL) {
        !           432:                for(parent=dp->parent; parent->parent!=NULL; parent=parent->parent)
        !           433:                        ;
        !           434:                s_append(sp, s_to_c(parent->addr));
        !           435:                s_append(sp, "' alias `");
        !           436:        }
        !           437:        s_append(sp, s_to_c(dp->addr));
        !           438: }
        !           439: 
        !           440: /* reject delivery */
        !           441: refuse(list, mp, cp, status)
        !           442:        dest *list;
        !           443:        message *mp;
        !           444:        char *cp;
        !           445:        int status;
        !           446: {
        !           447:        string *errstr=s_new();
        !           448:        dest *dp;
        !           449:        int rv=0;
        !           450: 
        !           451:        dp = d_rm(&list);
        !           452:        mkerrstr(errstr, mp, dp, list, cp, status);
        !           453:        /*
        !           454:         * if on a tty just report the error.  Otherwise send mail
        !           455:         * reporting the error.  N.B. To avoid mail loops, don't
        !           456:         * send mail reporting a failure of mail to reach the postmaster.
        !           457:         */
        !           458:        if (onatty) {
        !           459:                fputs(s_to_c(errstr), stderr);
        !           460:                savemail = 1;
        !           461:                rv = 1;
        !           462:        } else {
        !           463:                if (strcmp(s_to_c(mp->replyaddr), "postmaster")!=0)
        !           464:                        rv = replymsg(errstr, mp, dp);
        !           465:                else
        !           466:                        rv = 1;
        !           467:        }
        !           468:        logrefusal(dp, mp, s_to_c(errstr));
        !           469:        s_free(errstr);
        !           470:        return rv;
        !           471: }
        !           472: 
        !           473: /* make the error message */
        !           474: mkerrstr(errstr, mp, dp, list, cp, status)
        !           475:        string *errstr;
        !           476:        message *mp;
        !           477:        dest *dp;
        !           478:        dest *list;
        !           479:        char *cp;
        !           480: {
        !           481:        dest *next;
        !           482:        char smsg[64];
        !           483: 
        !           484:        /* list all aliases */
        !           485:        s_append(errstr, "Mail to `");
        !           486:        appaddr(errstr, dp);
        !           487:        for(next = d_rm(&list); next != NULL; next = d_rm(&list)) {
        !           488:                s_append(errstr, "', '");
        !           489:                appaddr(errstr, next);
        !           490:                d_insert(&dp, next);
        !           491:        }
        !           492:        s_append(errstr, "' from '");
        !           493:        s_append(errstr, s_to_c(mp->sender));
        !           494:        s_append(errstr, "' failed.\n");
        !           495: 
        !           496:        /* >> and | deserve different flavored messages */
        !           497:        switch(dp->status) {
        !           498:        case d_pipe:
        !           499:                s_append(errstr, "The mailer `");
        !           500:                s_append(errstr, s_to_c(dp->repl1));
        !           501:                sprintf(smsg, "' returned error status %x.\n", status);
        !           502:                s_append(errstr, smsg);
        !           503:                s_append(errstr, "The error message was:\n");
        !           504:                s_append(errstr, cp);
        !           505:                break;
        !           506:        default:
        !           507:                s_append(errstr, "The error message was:\n");
        !           508:                s_append(errstr, cp);
        !           509:                break;
        !           510:        }
        !           511: }
        !           512: 
        !           513: /*
        !           514:  *  reply with up to 1024 characters of the
        !           515:  *  original message
        !           516:  */
        !           517: replymsg(errstr, mp, dp)
        !           518:        string *errstr;
        !           519:        message *mp;
        !           520:        dest *dp;
        !           521: {
        !           522:        message *refp = m_new();
        !           523:        dest *ndp;
        !           524:        char *rcvr;
        !           525:        int rv;
        !           526: 
        !           527:        rcvr = dp->status==d_eloop ? "postmaster" : s_to_c(mp->replyaddr);
        !           528:        ndp = d_new(s_copy(rcvr));
        !           529:        s_append(refp->sender, "postmaster");
        !           530:        s_append(refp->replyaddr, "postmaster");
        !           531:        s_append(refp->date, thedate());
        !           532:        s_append(refp->body, s_to_c(errstr));
        !           533:        s_append(refp->body, "\nThe message began:\n");
        !           534:        s_nappend(refp->body, s_to_c(mp->body), 8*1024);
        !           535:        refp->size = strlen(s_to_c(refp->body));
        !           536:        rv = send(ndp, refp, 0);
        !           537:        m_free(refp);
        !           538:        d_free(ndp);
        !           539:        return rv;
        !           540: }
        !           541: 

unix.superglobalmegacorp.com

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