Annotation of 41BSD/cmd/delivermail/v6-mail.c, revision 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.