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

unix.superglobalmegacorp.com

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