Annotation of researchv8dc/cmd/upas/send/send.c, revision 1.1

1.1     ! root        1: #include <stdio.h>
        !             2: #include <sys/types.h>
        !             3: #include <signal.h>
        !             4: #include <pwd.h>
        !             5: #include <sys/stat.h>
        !             6: #include <time.h>
        !             7: #include <sys/timeb.h>
        !             8: #include "letter.h"
        !             9: #include "mail.h"
        !            10: #include "string.h"
        !            11: 
        !            12: 
        !            13: /* configuration */
        !            14: #define DEAD "dead.letter"
        !            15: #define MAILMODE (~0644)               /* mode of created mail */
        !            16: #define MAXFORWARD 32
        !            17: #define MAXHOP 5
        !            18: 
        !            19: /* imports */
        !            20: extern char *basename();
        !            21: extern int (*signal())();
        !            22: extern char *getsysname();
        !            23: extern char *stringin();
        !            24: extern char *getarg();
        !            25: extern char *getenv();
        !            26: extern char *mailpath();
        !            27: extern char *upaspath();
        !            28: extern void lock();
        !            29: extern void unlock();
        !            30: extern int rewrite();
        !            31: extern int getrules();
        !            32: extern long getunix();
        !            33: extern void putunix();
        !            34: extern void putrfunix();
        !            35: extern FILE *popen();
        !            36: extern char *getlogin();
        !            37: extern char *asctime();
        !            38: extern struct tm *localtime();
        !            39: extern char *timezone();
        !            40: 
        !            41: /* exported */
        !            42: char *thissys;         /* name of this system */
        !            43: char *network = "uucp";        /* name of network mail is coming from */
        !            44: int onatty;
        !            45: int rmail;             /* true if not executed as 'mail' */
        !            46: 
        !            47: /* global to this module */
        !            48: #define LETTERNAME 0
        !            49: #define DEVTTY NOFILE-1
        !            50: static int error;
        !            51: static char *myname;           /* name of this program */
        !            52: 
        !            53: /* predeclared */
        !            54: static void saveletter();
        !            55: static int saveonint(), done();
        !            56: static int send();
        !            57: static int append_to_file();
        !            58: static int pipe_to_cmd();
        !            59: static long getfrom();
        !            60: 
        !            61: extern void
        !            62: sendmail(ac, av)
        !            63:        int ac;
        !            64:        char *av[];
        !            65: {
        !            66:        int chkfl;              /* check forward list */
        !            67:        int ind=1;
        !            68:        int (*rc)();
        !            69:        char sender[ADDRSIZE];
        !            70:        char date[DATESIZE];
        !            71:        long bodyoffset;
        !            72:        letter *lp;
        !            73: 
        !            74:        /* avoid hanging dk lines (HACK!!!!!!!!) */
        !            75:        close(DEVTTY);
        !            76: 
        !            77:        myname = basename(av[0]);
        !            78:        rmail = chkfl = strcmp(myname, "mail") != 0;
        !            79:        onatty = isatty(0);
        !            80:        thissys = getsysname();
        !            81: 
        !            82:        /* make temporary */
        !            83:        rc = signal(SIGINT, done);
        !            84:        inittmp();
        !            85: 
        !            86:        /* get network (default uucp) */
        !            87:        if (av[1][0] == '-' && av[1][1] == 'N') {
        !            88:                if (av[1][2] == '\0') {
        !            89:                        network = av[2];
        !            90:                        ind++;
        !            91:                } else {
        !            92:                        network = &(av[1][2]);
        !            93:                }
        !            94:                ind++;
        !            95:        }
        !            96: 
        !            97:        /* read letter */
        !            98:        (void)signal(SIGINT, saveonint);
        !            99:        lp = lopen(LETTERNAME, "w");
        !           100:        copyto(stdin, lp, onatty, 1);
        !           101:        if (ltell(lp) == 0L)
        !           102:                done();
        !           103:                
        !           104:        /* send */
        !           105:        if (!error) {
        !           106:                (void)getrules();
        !           107:                lp = lopen(LETTERNAME, "r");
        !           108:                bodyoffset = getfrom(lp, sender, date);
        !           109:                (void)signal(SIGINT, rc);
        !           110:                for (; ind<ac; ind++) {
        !           111:                        letseek(lp, bodyoffset);
        !           112:                        error += send(lp, sender, date, av[ind], chkfl, 0);
        !           113:                }
        !           114:        }
        !           115:        if (error && onatty)
        !           116:                saveletter(lp);
        !           117:        (void)done();
        !           118: }
        !           119: 
        !           120: /* come here on interrupt while reading in letter */
        !           121: static int
        !           122: saveonint() {
        !           123:        (void)signal(SIGINT, saveonint);
        !           124:        error++;
        !           125: }
        !           126: 
        !           127: /* come here to finish up */
        !           128: static int
        !           129: done() {
        !           130:        unlock();
        !           131:        releasetmp();
        !           132:        exit(error);
        !           133: }
        !           134: 
        !           135: /* save the letter in dead.letter */
        !           136: static void
        !           137: saveletter(lp)
        !           138:        letter *lp;
        !           139: {
        !           140:        FILE *malf;
        !           141:        char where[PATHSIZE];
        !           142:        char *home = getenv("HOME");
        !           143: 
        !           144:        (void)setgid(getgid());
        !           145:        (void)setuid(getuid());
        !           146:        if (home != NULL) {
        !           147:                strcpy(where, home);
        !           148:                strcat(where, "/");
        !           149:        } else
        !           150:                *where = '\0';
        !           151:        strcat(where, DEAD);
        !           152:        malf = fopen(where, "w");
        !           153:        if (malf == NULL) {
        !           154:                fprintf(stderr, "mail: cannot open %s\n", where);
        !           155:                return;
        !           156:        }
        !           157:        letseek(lp, (long)0);
        !           158:        copyfrom(lp, malf);
        !           159:        fclose(malf);
        !           160:        printf("Mail saved in %s\n", where);
        !           161: }
        !           162: 
        !           163: /*
        !           164:  *     Send a letter.  Return 0 if all went well.
        !           165:  */
        !           166: static int
        !           167: send(lp, sender, date, rcvr, chkfl, hop)
        !           168:        letter *lp;
        !           169:        char *sender, *date, *rcvr;
        !           170:        int chkfl;
        !           171:        int hop;
        !           172: {
        !           173:        int rv, notinfl;
        !           174:        char dest[ADDRSIZE], rest[ADDRSIZE], cmd[CMDSIZE], format[32], sysname[64];
        !           175: 
        !           176:        if ((notinfl = rewrite(rcvr, sender, chkfl, cmd)) < 0) {
        !           177:                fprintf(stderr, "mail: can't understand address %s\n", dest);
        !           178:                return 1;
        !           179:        }
        !           180:        if (cmd[0]=='\0')
        !           181:                rv = append_to_file(lp, sender, date, rcvr, chkfl, hop);
        !           182:        else
        !           183:                rv = pipe_to_cmd(lp, sender, date, rcvr, cmd,
        !           184:                        chkfl && notinfl);
        !           185:        return rv;
        !           186: }
        !           187: 
        !           188: /*
        !           189:  *     Put mail into a mail file in the standard place.
        !           190:  */
        !           191: static int
        !           192: append_to_file(lp, sender, date, rcvr, chkfl, hop)
        !           193:        letter *lp;
        !           194:        char *sender, *date, *rcvr;
        !           195:        int hop;
        !           196: {
        !           197:        register mask;
        !           198:        struct passwd *pw, *getpwnam();
        !           199:        struct stat stbuf;
        !           200:        char file[PATHSIZE];
        !           201:        char sendto[CMDSIZE];
        !           202:        int exists;
        !           203:        FILE *malf;
        !           204:        char *p;
        !           205:        int i;
        !           206: 
        !           207:        if (strcmp(rcvr, "-") == 0)
        !           208:                return(1);
        !           209:        if (strchr(rcvr, '/') != NULL) {
        !           210:                fprintf(stderr, "mail: illegal name %s\n", rcvr);
        !           211:                return(0);
        !           212:        }
        !           213:        strcpy(file, mailpath(rcvr));
        !           214:        switch (delivery_status(file, sendto) & MFTYPE) {
        !           215:        case MF_NORMAL:
        !           216:                /* normal message */
        !           217:                break;
        !           218:        case MF_FORWARD:
        !           219:                /* look for possible forwarding loop */
        !           220:                for (i = 0, p = sender-1; p != NULL; p = strchr(p+1, '!'))
        !           221:                        if (strncmp(thissys, p+1, strlen(thissys))==0)
        !           222:                                i++;
        !           223:                if (i > MAXHOP) {
        !           224:                        logsend(rcvr, sender, date, "remote-mail-loop-err");
        !           225:                        fprintf(stderr, "mail: remote mail loop\n");
        !           226:                        break;
        !           227:                }
        !           228: 
        !           229:                /* forward message */
        !           230:                return forward_to(lp, rcvr, sender, date, sendto, hop);
        !           231:        case MF_PIPE:
        !           232:                /* pipe to a command */
        !           233:                (void)stat(file, &stbuf);
        !           234:                return pipe_to(lp, rcvr, sender, date, sendto, stbuf.st_uid,
        !           235:                               stbuf.st_gid);
        !           236:        }
        !           237:        exists = stat(file, &stbuf);
        !           238:        if ((pw = getpwnam(rcvr)) == NULL) {
        !           239:                if (exists < 0) {
        !           240:                        if (chkfl) {
        !           241:                                refuse(lp,sender, date, rcvr, "addressee unknown.");
        !           242:                                return(0);
        !           243:                        }
        !           244:                        fprintf(stderr, "mail: can't send to %s\n", rcvr);
        !           245:                        return 1;
        !           246:                }
        !           247:        } else {
        !           248:                stbuf.st_uid = pw->pw_uid;
        !           249:                stbuf.st_gid = pw->pw_gid;
        !           250:        }
        !           251:        mask = umask(MAILMODE);
        !           252:        lock(file);
        !           253:        malf = fopen(file, "a");
        !           254:        umask(mask);
        !           255:        if (malf == NULL) {
        !           256:                fprintf(stderr, "mail: cannot append to %s\n", file);
        !           257:                logsend(rcvr, sender, date, "append-err");
        !           258:                return 1;
        !           259:        }
        !           260:        if (exists < 0)
        !           261:                chown(file, stbuf.st_uid, stbuf.st_gid);
        !           262:        fprintf(malf, "%s%s %s\n", FROM, sender, date);
        !           263:        copyfrom(lp, malf);
        !           264:        fputs("\n", malf);
        !           265:        fclose(malf);
        !           266:        unlock();
        !           267:        logsend(rcvr, sender, date, "delivered");
        !           268:        notify(rcvr, sender);   /* let him know it right away! */
        !           269:        return 0;
        !           270: }
        !           271: 
        !           272: /*
        !           273:  *     Pipe the mail into a command.  This is either for remote
        !           274:  *     mail or specially handled mail.  Remote mail is distinguished
        !           275:  *     by a non-null string as the destination.
        !           276:  */
        !           277: static int
        !           278: pipe_to_cmd(lp, sender, date, rcvr, cmd, chkfl)
        !           279:        letter *lp;
        !           280:        char *sender, *date, *rcvr, *cmd;
        !           281:        int chkfl;
        !           282: {
        !           283:        FILE *fp;
        !           284:        char errbuf[CMDSIZE];
        !           285:        char reason[2*CMDSIZE];
        !           286:        long pos, status;
        !           287: 
        !           288:        /* check forwarding (what anti-social crap!) */
        !           289:        if (chkfl) {
        !           290:                if (rewrite(sender, "", chkfl, (char *)NULL) != 0) {
        !           291:                        refuse(lp, sender, date, rcvr,
        !           292:                                "forwarding to this system disallowed.");
        !           293:                        return(0);
        !           294:                }
        !           295:        }
        !           296: 
        !           297:        /* do it */
        !           298:        if ((fp=popen(cmd, getuid(), getgid())) == NULL) {
        !           299:                fprintf(stderr, "mail: can't pipe to network mailer\n");
        !           300:                exit(1);
        !           301:        }
        !           302:        pos = ltell(lp);
        !           303:        putrfunix(sender, date, thissys, fp);
        !           304:        copyfrom(lp, fp);
        !           305:        status = pclose(fp, errbuf, CMDSIZE);
        !           306:        if (status==0) {
        !           307:                logsend(rcvr, sender, date, "remote");
        !           308:                return 0;
        !           309:        } else {
        !           310:                logsend(rcvr, sender, date, "remote-err");
        !           311:                logsend("", cmd, "", "remote-err");
        !           312:                sprintf(reason, "\"%s\"\nwas unable to send your mail.  It returned the status 0x%x.\nStderr was:\n%s",
        !           313:                        cmd, status, errbuf);
        !           314:                (void)letseek(lp, pos);
        !           315:                refuse(lp, sender, date, rcvr, reason);
        !           316:                return 0;
        !           317:        }
        !           318: }
        !           319: 
        !           320: 
        !           321: /* return to sender, address unknown, no such number, no such phone... */
        !           322: refuse(lp, sender, date, rcvr, reason)
        !           323:        letter *lp;
        !           324:        char *sender, *date, *rcvr, *reason;
        !           325: {
        !           326:        FILE *pf;
        !           327:        char cbuf[CMDSIZE];
        !           328: 
        !           329:        sprintf(cbuf, "PATH=/bin:/usr/bin mail %s", sender);
        !           330:        if ((pf = popen(cbuf, getuid(), getgid())) == NULL)
        !           331:                return;
        !           332:        fprintf(pf, "Mail to %s failed. %s\nMessage was:\n", rcvr, reason);
        !           333:        fprintf(pf, "%s%s %s\n", FROM, sender, date);
        !           334:        copyfrom(lp, pf);
        !           335:        pclose(pf, 0, 0);
        !           336:        logsend(rcvr, sender, date, "refused");
        !           337: }
        !           338: 
        !           339: /* forward mail to a list of people */
        !           340: forward_to(lp, rcvr, sender, date, list, hop)
        !           341:        letter *lp;
        !           342:        char *rcvr, *sender, *date, *list;
        !           343:        int hop;
        !           344: {
        !           345:        char dest[ADDRSIZE];
        !           346:        char *p;
        !           347:        int rv=0;
        !           348: 
        !           349:        if (hop > MAXFORWARD) {
        !           350:                fprintf(stderr, "mail: forwarding loop!!\n");
        !           351:                logsend(rcvr, sender, date, "forward-loop-err");
        !           352:                return 1;
        !           353:        }
        !           354:        for (p = list; (p = getarg(dest, p)) != NULL; ) {
        !           355:                (void)letseek(lp, (long)0);
        !           356:                rv += send(lp, sender, date, dest, 0, ++hop);
        !           357:        }
        !           358:        return rv;
        !           359: }
        !           360: 
        !           361: #define SU 0   /* super-duper user uid */
        !           362: 
        !           363: /* change uid to the receiver and perform the command */
        !           364: pipe_to(lp, rcvr, sender, date, cmd, uid, gid)
        !           365:        letter *lp;
        !           366:        char *rcvr, *sender, *date, *cmd;
        !           367: {
        !           368:        FILE *fp;
        !           369:        int i;
        !           370: 
        !           371:        /* do it */
        !           372:        if ((fp=popen(cmd, uid, gid)) == NULL) {
        !           373:                fprintf(stderr, "mail: can't pipe to network mailer\n");
        !           374:                return 1;
        !           375:        }
        !           376:        putunix(sender, date, fp);
        !           377:        copyfrom(lp, fp);
        !           378:        if ((i=pclose(fp, 0, 0))==0) {
        !           379:                logsend(rcvr, sender, date, "pipe_to");
        !           380:                return 0;
        !           381:        } else {
        !           382:                logsend(rcvr, sender, date, "pipe_to_err");
        !           383:                logsend("", cmd, "", "pipe_to_err");
        !           384:                fprintf(stderr, "mail: Pipe to \"%s\" returns error status %d\n",
        !           385:                        cmd, i);
        !           386:                return 1;
        !           387:        }
        !           388: }
        !           389: 
        !           390: /* default sender */
        !           391: static void
        !           392: defaultsender(sender, date)
        !           393:        char *sender;   /* filled by defaultsender */
        !           394:        char *date;     /* filled by defaultsender */
        !           395: {
        !           396:        char *tp, *dp;
        !           397:        struct timeb timbuf;
        !           398:        struct tm *bp;
        !           399:        long thetime;
        !           400: 
        !           401:        (void)strcpy(sender, getlogin());
        !           402:        ftime(&timbuf);
        !           403:        thetime = timbuf.time;
        !           404:        bp = localtime(&thetime);
        !           405:        dp = asctime(bp);
        !           406:        tp = timezone(timbuf.timezone, bp->tm_isdst);
        !           407:        sprintf(date, "%.16s %.3s %.4s", dp, tp, dp+20);
        !           408: }
        !           409: 
        !           410: /* Get/parse a unix header. */
        !           411: static long
        !           412: getfrom(lp, sender, date)
        !           413:        letter *lp;
        !           414:        char *sender, *date;
        !           415: {
        !           416:        char line[FROMLINESIZE];
        !           417:        long n=0;
        !           418: 
        !           419:        defaultsender(sender, date);
        !           420:        initgetunix();
        !           421:        while (lgets(line, sizeof(line), lp) != NULL) {
        !           422:                if (getunix(line, sender, date) == 0)
        !           423:                        break;
        !           424:                n = ltell(lp);
        !           425:        }
        !           426: 
        !           427:        return n;
        !           428: }

unix.superglobalmegacorp.com

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