Annotation of 41BSD/cmd/delivermail/v6-mail.c, revision 1.1.1.1

1.1       root        1: #
                      2: 
                      3: /*
                      4:  * mail command usage
                      5:  *     mail [-yn]
                      6:  *             prints your mail
                      7:  *     mail people
                      8:  *             sends standard input to people
                      9:  *
                     10:  *     mail -r machine user people
                     11:  *             sends mail from the network
                     12:  *
                     13:  * if NOTROOT is defined, don't run as root.
                     14:  */
                     15: 
                     16: #define        SIGINT          2
                     17: #define DIRECT         040000
                     18: #define RMAILCMD       "/usr/net/bin/sendmail"
                     19: #define GETUID()       (getuid() & 0377)
                     20: #define        SPOOLDIR        "/usr/spool/mail/"
                     21: #define NOTROOT                $
                     22: 
                     23: struct inode {
                     24:        char minor;
                     25:        char major;
                     26:        int inumber;
                     27:        int flags;
                     28:        char nlinks;
                     29:        char uid;
                     30:        char gid;
                     31:        char size0;
                     32:        int size1;
                     33:        int addr[8];
                     34:        int actime[2];
                     35:        int modtime[2];
                     36: } inode;
                     37: 
                     38: char   lettmp[] "/tmp/maXXXXX";
                     39: char   preptmp[] "/tmp/mbXXXXX";
                     40: int    pwfil;
                     41: int    chew;
                     42: int    errs;
                     43: char   *strcat(), *strcpy();
                     44: 
                     45: main(argc, argv)
                     46: char **argv;
                     47: {
                     48:        register int me;
                     49:        extern int fout;
                     50:        int uf, delexit();
                     51:        char namebuf[20];
                     52: 
                     53:        mktemp(lettmp);
                     54:        mktemp(preptmp);
                     55:        unlink(lettmp);
                     56:        unlink(preptmp);
                     57:        me = GETUID();
                     58:        if (getname(me, namebuf) < 0) {
                     59:                printf("Who are you?\n");
                     60:                delexit(1);
                     61:        }
                     62:        if (argc < 2)
                     63:                goto hitit;
                     64:        for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++)
                     65:        switch(argv[0][1]) {
                     66:                register char *cp, *np;
                     67: 
                     68:                case 'y':
                     69:                case 'n':
                     70:                        argc++, argv--;
                     71: hitit:
                     72:                        printmail(argc, argv, namebuf);
                     73:                        delexit(0);
                     74: 
                     75:                case 'r':
                     76:                        if (argc < 2)
                     77:                                continue;
                     78:                case 'f':
                     79:                        if (argc < 1)
                     80:                                continue;
                     81:                        if (!equal("network", namebuf) && me != 0) {
                     82:                                printf("Nice try!\n");
                     83:                                delexit(1);
                     84:                        }
                     85:                        chew++;
                     86:                        np = namebuf;
                     87:                        for (cp = argv[1]; *cp; cp++)
                     88:                                *np++ = *cp;
                     89:                        if (argv[0][1] == 'r')
                     90:                        {
                     91:                                argc--, argv++;
                     92:                                *np++ = ':';
                     93:                                for (cp = argv[1]; *cp; cp++)
                     94:                                        *np++ = *cp;
                     95:                        }
                     96:                        *np++ = 0;
                     97:                        argc--, argv++;
                     98:                        continue;
                     99:        }
                    100:        if ((signal(SIGINT, 01) & 01) == 0)
                    101:                signal(SIGINT, delexit);
                    102:        unlink(lettmp);
                    103: # ifdef NOTROOT
                    104:        fout = creat(lettmp, 0666);
                    105: # else
                    106:        fout = creat(lettmp, 0600);
                    107: # endif
                    108:        if (fout < 0) {
                    109:                fout = 1;
                    110:                perror(lettmp);
                    111:                delexit(1);
                    112:        }
                    113:        argc++, argv--;
                    114:        bulkmail(argc, argv, namebuf);
                    115:        delexit(0);
                    116: }
                    117: 
                    118: printmail(argc, argv, name)
                    119: char **argv;
                    120: char *name;
                    121: {
                    122:        extern int fin, fout;
                    123:        register n, c, f;
                    124:        char *mname;
                    125: 
                    126:        mname = cat(SPOOLDIR, name);
                    127:        if (stat(mname, &inode)>=0 && inode.nlinks==1 &&
                    128:                fopen(mname, &fin)>=0 && (c = getchar())) {
                    129:                putchar(c);
                    130:                getput();
                    131:                close(fin);
                    132:                c = 'x';
                    133:                if (argc<2) {
                    134:                        if (ttyn(0)!='x') {
                    135:                                printf("Save?");
                    136:                                fin = 0;
                    137:                                c = getchar();
                    138:                        }
                    139:                } else
                    140:                        c = argv[1][1];
                    141:                if (!any(c, "yn"))
                    142:                        delexit(0);
                    143:                if (c == 'y') {
                    144:                        if (accesss("mbox")) {
                    145:                                printf("Saved mail in 'mbox'\n");
                    146:                                prepend(mname, "mbox", GETUID());
                    147:                                unlink(mname);
                    148:                        } else
                    149:                                printf("In wrong directory\n");
                    150:                } else
                    151:                        unlink(mname);
                    152:        } else
                    153:                printf("No mail.\n");
                    154: }
                    155: 
                    156: bulkmail(argc, argv, from)
                    157: char **argv, *from;
                    158: {
                    159:        extern int fin, fout;
                    160:        register int c;
                    161:        register char *cp;
                    162:        char linebuf[128];
                    163:        int tbuf[2], ttyn1;
                    164: 
                    165:        fin = 0;
                    166:        (&fin)[1] = 0;
                    167:        time(tbuf);
                    168:        ttyn1 = ttyn(1);
                    169:        if (ttyn1 < 033) {
                    170:                ttyn1 =+ 'a' - 1;
                    171:                ttyn1 =<< 8;
                    172:                ttyn1 =| '^';
                    173:        }
                    174:        printf("From %s  tty%c  %s", from, ttyn1, ctime(tbuf));
                    175: 
                    176:        /*
                    177:         * If delivering mail from the network via mail -r,
                    178:         * Strip the leading line and throw it away, as long
                    179:         * as it begins with "From ..."
                    180:         */
                    181: 
                    182:        if (chew) {
                    183:                cp = linebuf;
                    184:                do {
                    185:                        c = getchar();
                    186:                        if (cp - linebuf < 120)
                    187:                                *cp++ = c;
                    188:                } while (c != '\n' && c != 0);
                    189:                *cp = '\0';
                    190:                if (linebuf[0] != 'F' || linebuf[1] != 'r' ||
                    191:                    linebuf[2] != 'o' || linebuf[3] != 'm')
                    192:                        printf("%s", linebuf);
                    193:        }
                    194:        getput();
                    195:        putchar('\n');
                    196:        flush();
                    197:        close(fout);
                    198:        while (--argc > 0)
                    199:                sendto(*++argv);
                    200:        delexit(errs);
                    201: }
                    202: 
                    203: sendto(person)
                    204: char *person;
                    205: {
                    206:        static int saved;
                    207:        extern int fout, fin;
                    208:        register char *filep;
                    209:        register int him;
                    210:        int i;
                    211: 
                    212:        if ((person[0] == 'i' || person[0] == 'I') && person[1] == ':')
                    213:                person += 2;
                    214:        for (i = 0; person[i] != '\0'; i++)
                    215:        {
                    216:                if (person[i] == ':')
                    217:                {
                    218:                        person[i] = '\0';
                    219:                        if (equal(person, "ing70") || equal(person, "ingres"))
                    220:                                person += i + 1;
                    221:                        else
                    222:                                person[i] = ':';
                    223:                        break;
                    224:                }
                    225:        }
                    226:        if (person[i] == ':' || equal(person, "msgs"))
                    227:        {
                    228:                int i = fork();
                    229:                int s;
                    230: 
                    231:                if (i < 0) {
                    232:                        perror("fork");
                    233:                        goto assback;
                    234:                }
                    235:                if (i == 0) {
                    236:                        close(0);
                    237:                        open(lettmp, 0);
                    238:                        if (any(':', person)) {
                    239:                                execl(RMAILCMD, "sendmail", person, 0);
                    240:                                execl("/usr/bin/sendmail", "sendmail", person, 0);
                    241:                                execl("/bin/sendmail", "sendmail", person, 0);
                    242:                                perror("sendmail");
                    243:                        } else {
                    244:                                execl("/usr/new/msgs", "msgs", "-s", 0);
                    245:                                execl("/usr/ucb/msgs", "msgs", "-s", 0);
                    246:                                execl("/usr/bin/msgs", "msgs", "-s", 0);
                    247:                        }
                    248:                        exit(12);
                    249:                }
                    250:                for (;;) {
                    251:                        register int j = wait(&s);
                    252:                        if (j == -1)
                    253:                                goto assback;
                    254:                        if (j == i)
                    255:                                break;
                    256:                }
                    257:                if ((s & 0377) != 0 || (s >> 8) == 12)
                    258:                        goto assback;
                    259:                return;
                    260:        }
                    261: 
                    262:        if ((him = getuserid(person)) == -1) {
                    263: assback:
                    264:                fout = 1;
                    265:                flush();
                    266:                printf("Can't send to %s.\n", person);
                    267:                errs++;
                    268:                if (ttyn(0)!='x' && saved==0) {
                    269:                        saved++;
                    270:                        if (accesss("dead.letter")) {
                    271:                                printf("Letter saved in 'dead.letter'\n");
                    272:                                prepend(lettmp, "dead.letter", GETUID());
                    273:                        } else
                    274:                                printf("In wrong directory\n");
                    275:                }
                    276:                return;
                    277:        }
                    278:        filep = cat(SPOOLDIR, person);
                    279:        lock(filep);
                    280:        prepend(lettmp, filep, him);
                    281:        unlock();
                    282: }
                    283: 
                    284: prepend(from, to, own)
                    285: char *from, *to;
                    286: {
                    287:        extern int fin, fout;
                    288:        register int sig;
                    289:        int statb[18];
                    290: 
                    291:        if (stat(to, statb) >= 0 && (statb[2] & 060000) != 0) {
                    292:                write(2, "Exotic destination\n", 19);
                    293:                delexit(1);
                    294:        }
                    295:        unlink(preptmp);
                    296:        if (fcreat(preptmp, &fout) < 0) {
                    297:                fout = 1;
                    298:                perror("mail");
                    299:                delexit(1);
                    300:        }
                    301:        chmod(preptmp, 0600);
                    302:        if (fopen(from, &fin) < 0) {
                    303:                close(fout);
                    304:                fout = 1;
                    305:                perror("mail");
                    306:                unlink(preptmp);
                    307:                return(0);
                    308:        }
                    309:        getput();
                    310:        close(fin);
                    311:        fopen(to, &fin);
                    312:        getput();
                    313:        close(fin);
                    314:        flush();
                    315:        close(fout);
                    316:        sig = signal(SIGINT, 01);
                    317:        unlink(to);
                    318:        if (fcreat(to, &fout) < 0) {
                    319:                unlink(preptmp);
                    320:                fout = 1;
                    321:                signal(SIGINT, sig);
                    322:                return(0);
                    323:        }
                    324: # ifdef NOTROOT
                    325:        chmod(to, 0666);
                    326: # else
                    327:        chmod(to, 0600);
                    328:        chown(to, own);
                    329: # endif
                    330:        if(stat(to, &inode) < 0 || inode.nlinks != 1) {
                    331:                close(fout);
                    332:                fout = 1;
                    333:                unlink(preptmp);
                    334:                signal(SIGINT, sig);
                    335:                return(0);
                    336:        }
                    337:        if (fopen(preptmp, &fin) < 0) {
                    338:                fout = 1;
                    339:                perror("mail");
                    340:                signal(SIGINT, sig);
                    341:                errs++;
                    342:                return(0);
                    343:        }
                    344:        getput();
                    345:        flush();
                    346:        close(fout);
                    347:        close(fin);
                    348:        fout = 1;
                    349:        signal(SIGINT, sig);
                    350:        return(1);
                    351: }
                    352: 
                    353: delexit(ex)
                    354: {
                    355:        unlock();
                    356:        unlink(lettmp);
                    357:        unlink(preptmp);
                    358:        exit(ex);
                    359: }
                    360: 
                    361: equal(as1, as2)
                    362: {
                    363:        register char *s1, *s2;
                    364: 
                    365:        s1 = as1;
                    366:        s2 = as2;
                    367:        while (*s1++ == *s2)
                    368:                if (*s2++ == 0)
                    369:                        return(1);
                    370:        return(0);
                    371: }
                    372: 
                    373: cat(ap1, ap2)
                    374: char *ap1, *ap2;
                    375: {
                    376:        register char *p1, *p2;
                    377:        static char fn[32];
                    378: 
                    379:        p1 = ap1;
                    380:        p2 = fn;
                    381:        while (*p2++ = *p1++);
                    382:        p2--;
                    383:        p1 = ap2;
                    384:        while (*p2++ = *p1++);
                    385:        return(fn);
                    386: }
                    387: 
                    388: getput()
                    389: {
                    390:        extern int errno;
                    391:        register c;
                    392: 
                    393:        while(c = getchar()) {
                    394:                errno = 0;
                    395:                putchar(c);
                    396:                if(errno) {
                    397:                        perror("mail");
                    398:                        delexit(1);
                    399:                }
                    400:        }
                    401: }
                    402: 
                    403: accesss(s1)
                    404: {
                    405:        if (access(".", 2) != -1 && (stat(s1, &inode)<0 || access(s1, 2)==0))
                    406:                return(1);
                    407:        return(0);
                    408: }
                    409: 
                    410: any(c, str)
                    411:        char *str;
                    412: {
                    413:        register char *f;
                    414: 
                    415:        f = str;
                    416:        while (*f)
                    417:                if (c == *f++)
                    418:                        return(1);
                    419:        return(0);
                    420: }
                    421: 
                    422: char   *maillock       = ".lock";              /* Lock suffix for mailname */
                    423: char   *lockname       = "/usr/spool/mail/tmXXXXXX";
                    424: char   locktmp[30];                            /* Usable lock temporary */
                    425: char   curlock[50];                            /* Last used name of lock */
                    426: int    locked;                                 /* To note that we locked it */
                    427: 
                    428: /*
                    429:  * Lock the specified mail file by setting the file mailfile.lock.
                    430:  * We must, of course, be careful to unlink the lock file by a call
                    431:  * to unlock before we stop.  The algorithm used here is to see if
                    432:  * the lock exists, and if it does, to check its modify time.  If it
                    433:  * is older than 30 seconds, we assume error and set our own file.
                    434:  * Otherwise, we wait for 5 seconds and try again.
                    435:  */
                    436: 
                    437: lock(file)
                    438: char *file;
                    439: {
                    440:        register int f;
                    441:        long age;
                    442:        struct inode sbuf;
                    443:        long curtime;
                    444: 
                    445:        if (file == (char *) 0) {
                    446:                printf("Locked = %d\n", locked);
                    447:                return(0);
                    448:        }
                    449:        if (locked)
                    450:                return(0);
                    451:        strcpy(curlock, file);
                    452:        strcat(curlock, maillock);
                    453:        strcpy(locktmp, lockname);
                    454:        mktemp(locktmp);
                    455:        unlink(locktmp);
                    456:        for (;;) {
                    457:                f = lock1(locktmp, curlock);
                    458:                if (f == 0) {
                    459:                        locked = 1;
                    460:                        return(0);
                    461:                }
                    462:                if (stat(curlock, &sbuf) < 0)
                    463:                        return(0);
                    464:                time(&curtime);
                    465:                age = * ((long *) sbuf.modtime);
                    466:                if (curtime < age + 30) {
                    467:                        sleep(5);
                    468:                        continue;
                    469:                }
                    470:                unlink(curlock);
                    471:        }
                    472: }
                    473: 
                    474: /*
                    475:  * Remove the mail lock, and note that we no longer
                    476:  * have it locked.
                    477:  */
                    478: 
                    479: unlock()
                    480: {
                    481: 
                    482:        if (locked)
                    483:                unlink(curlock);
                    484:        locked = 0;
                    485: }
                    486: 
                    487: /*
                    488:  * Attempt to set the lock by creating the temporary file,
                    489:  * then doing a link/unlink.  If it fails, return -1 else 0
                    490:  */
                    491: 
                    492: lock1(tempfile, name)
                    493:        char tempfile[], name[];
                    494: {
                    495:        register int fd;
                    496: 
                    497:        fd = creat(tempfile, 0);
                    498:        if (fd < 0)
                    499:                return(-1);
                    500:        close(fd);
                    501:        if (link(tempfile, name) < 0) {
                    502:                unlink(tempfile);
                    503:                return(-1);
                    504:        }
                    505:        unlink(tempfile);
                    506:        return(0);
                    507: }
                    508: 
                    509: /*
                    510:  * Concatenate s2 on the end of s1.  S1's space must be large enough.
                    511:  * Return s1.
                    512:  */
                    513: 
                    514: char *
                    515: strcat(s1, s2)
                    516: register char *s1, *s2;
                    517: {
                    518:        register os1;
                    519: 
                    520:        os1 = s1;
                    521:        while (*s1++)
                    522:                ;
                    523:        *--s1;
                    524:        while (*s1++ = *s2++)
                    525:                ;
                    526:        return(os1);
                    527: }
                    528: 
                    529: /*
                    530:  * Copy string s2 to s1.  s1 must be large enough.
                    531:  * return s1
                    532:  */
                    533: 
                    534: char *
                    535: strcpy(s1, s2)
                    536: register char *s1, *s2;
                    537: {
                    538:        register os1;
                    539: 
                    540:        os1 = s1;
                    541:        while (*s1++ = *s2++)
                    542:                ;
                    543:        return(os1);
                    544: }

unix.superglobalmegacorp.com

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