Annotation of researchv8dc/cmd/upas/send/send.c, revision 1.1.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.