Annotation of 42BSD/undoc/v6mail.c, revision 1.1

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

unix.superglobalmegacorp.com

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