Annotation of 43BSDTahoe/undoc/v6mail.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * v6mail
        !             3:  */
        !             4: #include <sysexits.h>
        !             5: 
        !             6: #include <sys/param.h>
        !             7: #include <sys/stat.h>
        !             8: #include <sys/dir.h>
        !             9: #include <sys/times.h>
        !            10: #include <ctype.h>
        !            11: #include <errno.h>
        !            12: #include <pwd.h>
        !            13: #include <signal.h>
        !            14: 
        !            15: char   *ctime(), *index(), *rindex(), *ctime(), *strcpy(), *getlogin();
        !            16: char   *mktemp();
        !            17: struct passwd *getpwnam(), *getpwuid();
        !            18: time_t time();
        !            19: struct utmp *getutmp();
        !            20: char   *getdate();
        !            21: int    errno;
        !            22: 
        !            23: #include <stdio.h>
        !            24: 
        !            25: #define MAILMODE 0644
        !            26: #define MSGSCMD "/usr/ucb/msgs"
        !            27: #define MAILDIR "/usr/spool/mail"
        !            28: 
        !            29: char   lettmp[]  = "/tmp/MaXXXXX";     /* keep letter before sending it */
        !            30: char   preptmp[] = "/tmp/mbXXXXX";     /* if prepending msg, use this file */
        !            31: int    chew;                           /* if true, strip extra from lines */
        !            32: int    dflag;                          /* if true, don't call sendmail */
        !            33: char   shopcnt[30] = "0";              /* hop count parameter for rmt mail */
        !            34: int    errs;                           /* no of errs in sending */
        !            35: char   deleteonly;                     /* if true, just delete mailbox */
        !            36: char   remname[50];                    /* if non-empty, from line extra */
        !            37: 
        !            38: main(argc, argv)
        !            39:        int argc;
        !            40:        char **argv;
        !            41: {
        !            42:        register int myuid;
        !            43:        int delexit();
        !            44:        char namebuf[128], *sn = NULL, logindir[60];
        !            45:        struct passwd *pwd;
        !            46: 
        !            47:        (void) mktemp(lettmp);
        !            48:        (void) mktemp(preptmp);
        !            49:        (void) unlink(lettmp);
        !            50:        (void) unlink(preptmp);
        !            51:        myuid = getuid();
        !            52:        logindir[0] = 0;
        !            53:        sn = getlogin();
        !            54:        if (sn == NULL || *sn == 0 || *sn == ' ') {
        !            55:                pwd = getpwuid(myuid);          /* will read passwd file */
        !            56:                if (pwd != NULL){
        !            57:                        sn = pwd->pw_name;
        !            58:                        (void) strcpy(logindir, pwd->pw_dir);
        !            59:                }
        !            60:                if (sn == NULL) {
        !            61:                        fprintf(stderr, "Who are you?\n");
        !            62:                        delexit(EX_OSFILE);
        !            63:                }
        !            64:        }
        !            65:        (void) strcpy(namebuf, sn);
        !            66:        if (argc < 2)
        !            67:                goto hitit;
        !            68:        for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++)
        !            69:        switch (argv[0][1]) {
        !            70: 
        !            71:        case 'y':
        !            72:        case 'n':
        !            73:                argc++, argv--;
        !            74: hitit:
        !            75:                printmail(argc, argv, namebuf, logindir);
        !            76:                delexit(EX_OK);
        !            77: 
        !            78:        case 'r':       /* one-arg -r--   -r addr */
        !            79:                if (argc < 2)
        !            80:                        continue;
        !            81:                /* ignore -r if not network or root */
        !            82:                if (strcmp("network", namebuf) == 0 || myuid == 0 ||
        !            83: /*###86 [lint] index arg. 1 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/
        !            84: /*###86 [lint] index arg. 2 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/
        !            85:                    strcmp("uucp", namebuf) == 0 || index('!', argv[1])) {
        !            86:                        (void) strcpy(namebuf, argv[1]);
        !            87:                        chew++;         /* eat From lines */
        !            88:                }
        !            89:                else
        !            90:                        (void) strcpy(remname, argv[1]);
        !            91:                argc--, argv++;
        !            92:                continue;
        !            93: 
        !            94:        case 'h':       /* hop count - used by network */
        !            95:                if (argc < 2)
        !            96:                        continue;
        !            97:                (void) strcpy(shopcnt, argv[1]);
        !            98:                argc--, argv++;
        !            99:                continue;
        !           100: 
        !           101:        case 'd':       /* really deliver this message */
        !           102:                dflag++;
        !           103:                continue;
        !           104: 
        !           105:        case 'D':       /* only delete the invokers mailbox */
        !           106:                deleteonly++;
        !           107:                goto hitit;             /* delete mail box, thats all */
        !           108:        }
        !           109:        /* if we are already ignoring signals, catch sigint */
        !           110:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        !           111:                (void) signal(SIGINT, delexit);
        !           112:        argc++, argv--;
        !           113:        bulkmail(argc, argv, namebuf);
        !           114:        delexit(EX_OK);
        !           115: }
        !           116: 
        !           117: printmail(argc, argv, name, logindir)
        !           118:        int argc;
        !           119:        char **argv;
        !           120:        char *name, *logindir;
        !           121: {
        !           122:        register int c;
        !           123:        FILE *fdin;
        !           124:        char sfnmail[60], mbox[120];
        !           125:        struct stat stb;
        !           126: 
        !           127:        (void) sprintf(sfnmail, "%s/%s", MAILDIR, name);
        !           128:        if (deleteonly) {
        !           129:                remove(sfnmail);
        !           130:                return;
        !           131:        }
        !           132:        fdin = fopen(sfnmail, "r");
        !           133:        if (fdin < 0 || fstat(fileno(fdin), &stb) < 0 || stb.st_size == 0) {
        !           134:                printf("No mail.\n");
        !           135:                return;
        !           136:        }
        !           137:        if (stb.st_nlink > 1) {
        !           138:                printf("%s: Too many links.\n", sfnmail);
        !           139:                return;
        !           140:        }
        !           141:        (void) getput(fdin, stdout);
        !           142:        (void) fclose(fdin);
        !           143:        (void) fflush(stdout);
        !           144:        c = 'y';
        !           145:        if (argc < 2) {
        !           146:                if (isatty(0)) {
        !           147:                        printf("Save (y or n) ?"); (void) fflush(stdout);
        !           148:                        c = getchar();
        !           149:                }
        !           150:        } else
        !           151:                c = argv[1][1];
        !           152:        switch (c) {
        !           153: 
        !           154:        default:
        !           155:                delexit(EX_OK);
        !           156:                /*NOTREACHED*/
        !           157: 
        !           158:        case 'x':
        !           159:                return;
        !           160: 
        !           161:        case 'y':
        !           162:                (void) sprintf(mbox, "%s/mbox", logindir);
        !           163:                if (writeable(mbox)) {
        !           164:                        perror(mbox);
        !           165:                        return;
        !           166:                }
        !           167:                printf("Saving mail in %s.\n", mbox);
        !           168:                if (append(sfnmail, mbox, getuid(), getgid()) == 0)
        !           169:                        return;
        !           170:                /* fall into... */
        !           171: 
        !           172:        case 'n':
        !           173:                remove(sfnmail);
        !           174:                return;
        !           175:        }
        !           176: }
        !           177: 
        !           178: bulkmail(argc, argv, from)
        !           179:        char **argv, *from;
        !           180: {
        !           181:        char linebuf[BUFSIZ];
        !           182:        FILE *fdout;
        !           183: 
        !           184:        if (dflag == 0) {
        !           185:                argv[0] = "sendmail";
        !           186:                argv[argc] = 0;
        !           187:                execv("/usr/lib/sendmail", argv);
        !           188:                perror("/usr/lib/sendmail");
        !           189:                _exit(1);
        !           190:        }
        !           191:        fdout = fopen(lettmp, "w");
        !           192:        if (fdout == NULL) {
        !           193:                perror(lettmp);
        !           194:                delexit(EX_OSFILE);
        !           195:        }
        !           196: 
        !           197:        /*
        !           198:         * If delivering mail from the network via mail -r,
        !           199:         * Strip the leading line and throw it away, as long
        !           200:         * as it begins with "From ..." (and preserve the date if poss.)
        !           201:         */
        !           202:        if (chew) {
        !           203:                if (fgets(linebuf, BUFSIZ, stdin) == 0)
        !           204:                        goto skip;
        !           205:                if (!strncmp(linebuf, "From ", 5) != 0)
        !           206:                        printfromline(fdout, getdate(linebuf), from);
        !           207:                else {
        !           208:                        printfromline(fdout, (char *)0, from);
        !           209:                        fprintf(fdout, "%s", linebuf);
        !           210:                }
        !           211:        } else
        !           212:                printfromline(fdout, (char *)0, from);
        !           213: skip:
        !           214:        if (remname[0])
        !           215:                fprintf(fdout, "(from %s)\n", remname);
        !           216:        if (getput(stdin, fdout) == 0)
        !           217:                delexit(EX_OSERR);
        !           218:        putc('\n', fdout);
        !           219:        (void) fclose(fdout);
        !           220:        while (--argc > 0)
        !           221:                sendto(*++argv);
        !           222:        delexit(errs);
        !           223: }
        !           224: 
        !           225: printfromline(fdout, date, from)
        !           226:        FILE *fdout;
        !           227:        char *date, *from;
        !           228: {
        !           229:        time_t t;
        !           230: 
        !           231:        if (date == NULL) {
        !           232:                t = time((time_t *)0);
        !           233:                date = ctime(&t);
        !           234:        }
        !           235:        fprintf(fdout, "From %s  %s", from, date);
        !           236: }
        !           237: 
        !           238: /* look over linebuf and return ptr to date, NULL if error */
        !           239: char *
        !           240: getdate(linebuf)
        !           241:        char *linebuf;
        !           242: {
        !           243:        register char *s = linebuf;
        !           244: 
        !           245: /*###244 [lint] index arg. 2 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/
        !           246: /*###244 [lint] index arg. 1 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/
        !           247:        while (s = index(' ', s))
        !           248:                if (!strncmp(s, " Sun ", 5) ||
        !           249:                    !strncmp(s, " Mon ", 5) ||
        !           250:                    !strncmp(s, " Tue ", 5) ||
        !           251:                    !strncmp(s, " Wed ", 5) ||
        !           252:                    !strncmp(s, " Thu ", 5) ||
        !           253:                    !strncmp(s, " Fri ", 5) ||
        !           254:                    !strncmp(s, " Sat ", 5))
        !           255:                        return (s + 1);
        !           256:        return (0);
        !           257: }
        !           258: 
        !           259: int    saved = 0;
        !           260: 
        !           261: sendto(person)
        !           262:        char *person;
        !           263: {
        !           264:        char mailboxname[BUFSIZ];
        !           265:        struct passwd *pwd;
        !           266: 
        !           267:        if (index('/', person)) {
        !           268:                if (!writeable(person)) {
        !           269:                        perror(person);
        !           270:                        return;
        !           271:                }
        !           272:                lock(person);
        !           273:                (void) append(lettmp, person, -1, -1);
        !           274:                unlock();
        !           275:                return;
        !           276:        }
        !           277:        pwd = getpwnam(person);
        !           278:        if (pwd) {
        !           279:                (void) sprintf(mailboxname, "%s/%s", MAILDIR, person);
        !           280:                lock(mailboxname);
        !           281:                (void) append(lettmp, mailboxname, pwd->pw_uid, pwd->pw_gid);
        !           282:                unlock();
        !           283:                return;
        !           284:        }
        !           285:        fprintf(stderr, "Can't send to %s.\n", person);
        !           286:        errs++;
        !           287:        if (!isatty(0) || saved)
        !           288:                return;
        !           289:        saved++;
        !           290:        if (!writeable("dead.letter")) {
        !           291:                perror("dead.letter");
        !           292:                return;
        !           293:        }
        !           294:        printf("Letter saved in 'dead.letter'\n");
        !           295:        (void) append(lettmp, "dead.letter", getuid(), getgid());
        !           296: }
        !           297: 
        !           298: #include <sys/socket.h>
        !           299: #include <net/in.h>
        !           300: 
        !           301: struct sockaddr_in biffaddr = { AF_INET, IPPORT_BIFFUDP };
        !           302: 
        !           303: append(from, to, uid, gid)
        !           304:        char *from, *to;
        !           305:        int uid, gid;
        !           306: {
        !           307:        register FILE *fdin, *fdout;
        !           308:        int ret;
        !           309:        struct stat stb;
        !           310:        char *cp, buf[100]; int f;
        !           311: 
        !           312:        if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) != S_IFREG) {
        !           313:                fprintf(stderr, "Not a plain file: %s\n", to);
        !           314:                goto fail;
        !           315:        }
        !           316:        fdout = fopen(to, "a");
        !           317:        if (fdout == NULL) {
        !           318:                perror(to);
        !           319:                goto fail;
        !           320:        }
        !           321:        if (uid != -1) {
        !           322:                (void) chown(to, uid, gid);
        !           323:                (void) chmod(to, MAILMODE);
        !           324:        }
        !           325:        if ((fdin = fopen(from, "r")) == NULL) {
        !           326:                perror(from);
        !           327:                return (0);
        !           328:        }
        !           329:        cp = rindex(to, '/');
        !           330:        if (cp) {
        !           331:                char *host = "localhost";
        !           332:                biffaddr.sin_addr.s_addr = rhost(&host);
        !           333: #if vax || pdp11
        !           334:                biffaddr.sin_port =
        !           335:                    (biffaddr.sin_port<<8) | ((biffaddr.sin_port>>8) & 0xff);
        !           336: #endif
        !           337:                f = socket(SOCK_DGRAM, 0, 0, 0);
        !           338:                (void) sprintf(buf, "%s@%d\n", cp+1, ftell(fdout)); 
        !           339:        }
        !           340:        ret = getput(fdin, fdout);
        !           341:        (void) fclose(fdin);
        !           342:        (void) fclose(fdout);
        !           343:        if (cp && f >= 0) {
        !           344:                send(f, &biffaddr, buf, strlen(buf)+1);
        !           345:                (void) close(f);
        !           346:        }
        !           347:        return (ret);
        !           348: fail:
        !           349:        errs++;
        !           350:        return (0);
        !           351: }
        !           352: 
        !           353: delexit(status)
        !           354:        int status;
        !           355: {
        !           356: 
        !           357:        (void) unlink(lettmp);
        !           358:        (void) unlink(preptmp);
        !           359:        exit(status);
        !           360: }
        !           361: 
        !           362: getput(fdin, fdout)
        !           363:        register FILE *fdin, *fdout;
        !           364: {
        !           365:        register int c;
        !           366: 
        !           367:        while ((c = getc(fdin)) != EOF) {
        !           368:                errno = 0;
        !           369:                putc(c, fdout);
        !           370:                if (errno) {
        !           371:                        perror("mail");
        !           372:                        return (0);
        !           373:                }
        !           374:        }
        !           375:        return (1);
        !           376: }
        !           377: 
        !           378: writeable(name)
        !           379:        char *name;
        !           380: {
        !           381:        struct stat stb;
        !           382:        char *cp;
        !           383:        int ok;
        !           384: 
        !           385:        if (stat(name, &stb) < 0) {
        !           386:                cp = rindex(name, '/');
        !           387:                if (cp)
        !           388:                        *cp = 0;
        !           389:                ok = access(cp ? "." : name, 2) == 0;
        !           390:                if (cp)
        !           391:                        *cp = '/';
        !           392:                return (ok);
        !           393:        }
        !           394:        return (access(name, 2) == 0);
        !           395: }
        !           396: 
        !           397: char   locktmp[30];                            /* Usable lock temporary */
        !           398: char   curlock[50];                            /* Last used name of lock */
        !           399: int    locked;                                 /* To note that we locked it */
        !           400: 
        !           401: /*
        !           402:  * Lock the specified mail file by setting the file mailfile.lock.
        !           403:  * We must, of course, be careful to unlink the lock file by a call
        !           404:  * to unlock before we stop.  The algorithm used here is to see if
        !           405:  * the lock exists, and if it does, to check its modify time.  If it
        !           406:  * is older than 30 seconds, we assume error and set our own file.
        !           407:  * Otherwise, we wait for 5 seconds and try again.
        !           408:  */
        !           409: lock(file)
        !           410:        char *file;
        !           411: {
        !           412:        register int f;
        !           413:        struct stat statbuf;
        !           414:        time_t curtime;
        !           415: 
        !           416:        if (locked)
        !           417:                return;
        !           418:        (void) sprintf(curlock, "%s%s", file, ".lock");
        !           419:        (void) sprintf(locktmp, "%s/tmXXXXXX", MAILDIR);
        !           420:        (void) mktemp(locktmp);
        !           421:        (void) unlink(locktmp);
        !           422:        for (;;) {
        !           423:                f = lock1(locktmp, curlock);
        !           424:                if (f == 0) {
        !           425:                        locked = 1;
        !           426:                        return;
        !           427:                }
        !           428:                if (stat(curlock, &statbuf) < 0)
        !           429:                        return;
        !           430:                (void) time(&curtime);
        !           431:                if (curtime < statbuf.st_mtime + 30) {
        !           432:                        sleep(5);
        !           433:                        continue;
        !           434:                }
        !           435:                (void) unlink(curlock);
        !           436:        }
        !           437: }
        !           438: 
        !           439: unlock()
        !           440: {
        !           441: 
        !           442:        if (locked)
        !           443:                (void) unlink(curlock);
        !           444:        locked = 0;
        !           445: }
        !           446: 
        !           447: /*
        !           448:  * Attempt to set the lock by creating the temporary file,
        !           449:  * then doing a link/unlink.  If it fails, return -1 else 0
        !           450:  */
        !           451: lock1(tempfile, name)
        !           452:        char tempfile[], name[];
        !           453: {
        !           454:        int fno;
        !           455: 
        !           456:        fno = creat(tempfile, 0400);
        !           457:        if (fno < 0)
        !           458:                return (-1);
        !           459:        (void) close(fno);
        !           460:        if (link(tempfile, name) < 0) {
        !           461:                (void) unlink(tempfile);
        !           462:                return (-1);
        !           463:        }
        !           464:        (void) unlink(tempfile);
        !           465:        return (0);
        !           466: }
        !           467: 
        !           468: remove(sfn)
        !           469:        char *sfn;
        !           470: {
        !           471:        int i;
        !           472: 
        !           473:        if (unlink(sfn) < 0) {
        !           474:                i = creat(sfn, MAILMODE);
        !           475:                if (i >= 0)
        !           476:                        (void) close(i);
        !           477:        }
        !           478: }

unix.superglobalmegacorp.com

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