Annotation of coherent/d/bin/mail/usermail/mail.c, revision 1.1

1.1     ! root        1: static char    *rcsrev = "$Revision: 3.4 $";
        !             2: static char    *rcshdr =
        !             3:        "$Header: /usr/local/src/dist/mail/usermail/RCS/mail.c,v 3.4 91/02/18 17:14:10 piggy Exp $";
        !             4: /*
        !             5:  * $Header: /usr/local/src/dist/mail/usermail/RCS/mail.c,v 3.4 91/02/18 17:14:10 piggy Exp $
        !             6:  * $Log:       /usr/local/src/dist/mail/usermail/RCS/mail.c,v $
        !             7:  * Revision 3.4        91/02/18  17:14:10      piggy
        !             8:  * Fixed "q" command so that it works with a non-setuid mail.
        !             9:  * 
        !            10:  * Revision 3.3        91/02/18  09:30:09      piggy
        !            11:  * Fixed two mishandlings of args[].
        !            12:  * 
        !            13:  * Revision 3.2        91/02/08  15:16:07      piggy
        !            14:  * Updated error messages to include malloc failures.
        !            15:  * 
        !            16:  * Revision 3.1        91/02/08  14:34:28      piggy
        !            17:  * Made csplit non-destructive.
        !            18:  * 
        !            19:  * Revision 3.0        91/02/07  15:19:14      piggy
        !            20:  * *** empty log message ***
        !            21:  * 
        !            22:  * Revision 2.13       90/03/30  16:16:19      wgl
        !            23:  * Correct seek pointer work within readmail.
        !            24:  * 
        !            25:  * Revision 2.12       90/03/12  14:19:08      wgl
        !            26:  * New version of send doing aliases in a different place.
        !            27:  * 
        !            28:  * Revision 2.11       90/03/08  16:41:15      wgl
        !            29:  * Add code to get signature file.
        !            30:  * 
        !            31:  * Revision 2.10       90/03/02  10:41:59      wgl
        !            32:  * Add the -a flag so that uucp does not look like it is coming from
        !            33:  * somewhere else.
        !            34:  * 
        !            35:  * Revision 2.9        90/03/01  11:17:19      wgl
        !            36:  * Final conversion to rely soley on ^A^A as separators.
        !            37:  * Effectively delete concept of m_hsize.
        !            38:  * 
        !            39:  * Revision 2.8        90/03/01  10:14:31      wgl
        !            40:  * Go buy separators, not "From_" lines.
        !            41:  * 
        !            42:  * Revision 2.7        90/02/28  17:11:41      wgl
        !            43:  * Add version print, add some changes to the message-id field.
        !            44:  * 
        !            45:  * Revision 2.6        90/02/28  16:42:09      wgl
        !            46:  * Version number fakeout.
        !            47:  * 
        !            48:  * Revision 2.5        90/02/28  16:19:44      wgl
        !            49:  * Try again to get versioin number right.
        !            50:  * 
        !            51:  * Revision 2.4        90/02/28  16:18:56      wgl
        !            52:  * Get version number right.
        !            53:  * 
        !            54:  * Revision 2.3        90/02/28  16:04:59      wgl
        !            55:  * Many changes; ripped out send.
        !            56:  * Changes are to make it work with uucp and internet mail.
        !            57:  * 
        !            58:  * Revision 1.6        89/02/22  05:34:00      bin
        !            59:  * Changes by rec to integrate with lauren's uumail.
        !            60:  * 
        !            61:  * Revision 1.5        88/09/01  14:49:01      bin
        !            62:  * Source administration: Re-install declaration of getenv. 
        !            63:  * It was inserted after epstein made his copy.
        !            64:  * 
        !            65:  * Revision 1.4        88/09/01  14:44:49      bin
        !            66:  * Mark Epsteins changes for ASKCC and for message scrolling, and interrupt
        !            67:  * handling during processing.
        !            68:  * 
        !            69:  * Revision 1.3        88/09/01  14:27:41      bin
        !            70:  * declare getenv to get rid of integer pointer pun error message.
        !            71:  * 
        !            72:  * Revision 1.2        88/09/01  11:02:23      bin
        !            73:  * Remove extra declaration of header which had rcs stuff in it.
        !            74:  * 
        !            75:  * Revision 1.1        88/09/01  10:55:34      bin
        !            76:  * Initial revision
        !            77:  * 
        !            78:  */
        !            79: /*
        !            80:  * The mail command.
        !            81:  * Coherent electronic postal system, user agent.
        !            82:  * With v3.0 this program no longer runs setuid.
        !            83:  * Modifications by rec january 1986 to include xmail.
        !            84:  *              by epstein november 1987 to include CC:
        !            85:  *              by epstein november 1987 to allow ^C exit to leave you in
        !            86:  *                                       mail command processor
        !            87:  *              by epstein november 1987 to substitute /usr/games/fortune
        !            88:  *                                       for printing encrypted messages
        !            89:  *             by rec february 1989 to tail to lauren weinstein's
        !            90:  *                     mail for alias expansion and uucp queuing.
        !            91:  *             by wgl January 1990 to handle uucp mail more directly.
        !            92:  */
        !            93: 
        !            94: char   isummary[] = "\
        !            95: \
        !            96: Command summary:\n\
        !            97:        d               Delete current message and print the next message\n\
        !            98:        m [user ...]    Mail current message to each named 'user'\n\
        !            99:        p               Print current message again\n\
        !           100:        q               Quit and update the mailbox\n\
        !           101:        r               Reverse direction of scan\n\
        !           102:        s [file ...]    Save message in each named 'file'\n\
        !           103:        t [user ...]    Mail standard input to each named 'user'\n\
        !           104:        w [file ...]    Save message in each named 'file' without its header\n\
        !           105:        x               Exit without updating mailbox\n\
        !           106:        newline         Print the next message\n\
        !           107:        .               Print current message again\n\
        !           108:        +               Print the next message\n\
        !           109:        -               Print the previous message\n\
        !           110:        EOF             Put undeleted mail back into mailbox and quit\n\
        !           111:        ?               Print this command summary\n\
        !           112:        !command        Pass 'command' to the shell to execute\n\
        !           113: If no 'file' is specified, 'mbox' in user's home directory is default.\n\
        !           114: If no 'user' is specified, the invoking user is default.\n\
        !           115: If the 'm', 'p', 't' commands are followed by an 'x',\n\
        !           116: then the public key cryptosystem is applied to the message.\n\
        !           117: \
        !           118: ";
        !           119: 
        !           120: #include "mail.h"
        !           121: 
        !           122: #define        NARGS   64              /* Maximum # args to interactive command */
        !           123: 
        !           124: extern char    *getenv();
        !           125: extern int     optind;
        !           126: extern char    *optarg;
        !           127: extern char    getopt();
        !           128: extern char    *malloc();
        !           129: int    csplit();
        !           130: char   *eat_ws();
        !           131: char   *find_ws();
        !           132: char   *revnop();
        !           133: 
        !           134: int    mflag;                  /* `You have mail.' message to recipient */
        !           135: int    rflag;                  /* Reverse order of print */
        !           136: int    qflag;                  /* Exit after interrrupts */
        !           137: int    pflag;                  /* Print mail */
        !           138: int    verbflag;               /* verbose */
        !           139: int    callmexmail;            /* Xmail modifier present */
        !           140: int    callmermail;            /* rmail modifier present */
        !           141: struct msg {
        !           142:        struct msg *m_next;             /* Link to next message */
        !           143:        struct msg *m_prev;             /* Link to previous message */
        !           144:        int     m_flag;                 /* Flags - non-zero if deleted */
        !           145:        int     m_hsize;                /* Size of header of message */
        !           146:        fsize_t m_seek;                 /* Start position of message */
        !           147:        fsize_t m_end;                  /* End of message */
        !           148: };
        !           149: struct msg     *m_first = NULL;        /* First message */
        !           150: struct msg     *m_last = NULL;         /* Last message */
        !           151: 
        !           152: struct tm      *tp;
        !           153: 
        !           154: char   iusage[] = "Bad command--type '?' for command summary\n";
        !           155: char   nombox[] = "No mailbox '%s'.\n";
        !           156: char   nomail[] = "No mail.\n";
        !           157: char   noperm[] = "Mailbox '%s' access denied.\n";
        !           158: char   moerr[] = "Cannot open mailbox '%s'\n";
        !           159: char   wrerr[] = "Write error on '%s'\n";
        !           160: char   nosave[] = "Cannot save letter in '%s'\n";
        !           161: char   allocerr[] = "%s: Can't malloc.\n";
        !           162: 
        !           163: FILE   *mfp;                           /* Mailbox stream */
        !           164: int    myuid;                          /* User-id of mail user */
        !           165: int    mygid;                          /* Group-id of mail user */
        !           166: char   myname[25];                     /* User name */
        !           167: char   myfullname[50];
        !           168: char   mymbox[256];                    /* $HOME/mbox           */
        !           169: char   mydead[256];                    /* $HOME/dead.letter    */
        !           170: char   mysig[256];                     /* $HOME/.sig.mail      */
        !           171: char   myalias[256];                   /* $HOME/.aliases       */
        !           172: char   spoolname[50] = SPOOLDIR;
        !           173: char   *mailbox = spoolname;
        !           174: char   cmdname[1024];          /* Command for x{en,de}code filter */
        !           175:                                /* and for tail recursion to uumail */
        !           176:                                /* and for editor recursion */
        !           177: 
        !           178: char   *args[NARGS];                   /* Interactive command arglist */
        !           179: char   msgline[NLINE];
        !           180: char   cline[NCLINE] = "+\n";
        !           181: char   *temp;                          /* Currently open temp file     */
        !           182: char   templ[] = "/tmp/mailXXXXXX";    /* Temp file name template      */
        !           183: char   *editname;                      /* name of editor               */
        !           184: char   *scatname;                      /* name of scat filter          */
        !           185: char   *askcc;                         /* Ask for CC: list? (YES/NO)   */
        !           186: 
        !           187: fsize_t        ftell();
        !           188: char   *getlogin();
        !           189: char   *mktemp();
        !           190: int    catchintr();
        !           191: int    catchpipe();
        !           192: char   asuser [32];
        !           193: 
        !           194: main(argc, argv)
        !           195: char *argv[];
        !           196: {
        !           197:        register char *ap;
        !           198:        char    c, *foo;
        !           199:        int i;
        !           200: 
        !           201:        logopen();
        !           202: 
        !           203:        /* Explicitly NULL out args.  */
        !           204:        for (i = 0; i < NARGS; ++i) {
        !           205:                args[i] = NULL;
        !           206:        }
        !           207: 
        !           208:        ap = argv[0];
        !           209:        if ( (foo=rindex(ap, '/')) != NULL )
        !           210:                ap = foo+1;
        !           211:        callmermail = (strcmp(ap, "rmail") == 0);
        !           212:        callmexmail = (strcmp(ap, "xmail") == 0);
        !           213: 
        !           214:        if (callmermail)
        !           215:                logdump("argv0 = rmail\n");
        !           216: 
        !           217:        asuser [0] = '\0';
        !           218:        signal(SIGINT, catchintr);
        !           219:        signal(SIGPIPE, catchpipe);
        !           220:        while ((c = getopt(argc, argv, "a:f:mpqrv")) != EOF) {
        !           221:                switch(c) {
        !           222:                case 'f':
        !           223:                        if (!callmermail)
        !           224:                                mailbox = optarg;
        !           225:                        break;
        !           226:                case 'a':
        !           227:                        strcpy(asuser, optarg);
        !           228:                        break;
        !           229:                case 'm':
        !           230:                        mflag++;
        !           231:                        break;
        !           232:                case 'p':
        !           233:                        pflag++;
        !           234:                        break;
        !           235:                case 'q':
        !           236:                        qflag++;
        !           237:                        break;
        !           238:                case 'r':
        !           239:                        rflag++;
        !           240:                        break;
        !           241:                case 'v':
        !           242:                        fprintf(stderr, "mail, ver. %s\n", revnop());
        !           243:                        verbflag++;
        !           244:                        break;
        !           245:                default:
        !           246:                        usage();
        !           247:                }
        !           248:        }
        !           249:        if (callmermail) 
        !           250:                verbflag = mflag = pflag = rflag = 0;
        !           251:        setname();
        !           252:        if (optind < argc) {
        !           253:                qflag = 1;
        !           254:                if ( send2(stdin, &argv[optind], (fsize_t)0,
        !           255:                                                 (fsize_t)MAXLONG, 1) != 0 )
        !           256:                        rmexit(1);
        !           257:        } else {
        !           258:                if ( ! pflag)
        !           259:                        callmexmail = 0;
        !           260:                commands();
        !           261:        }
        !           262:        rmexit(0);
        !           263: }
        !           264: 
        !           265: /*
        !           266:  * Setup all the identities for the current user.
        !           267:  */
        !           268: setname()
        !           269: {
        !           270:        register struct passwd *pwp;
        !           271:        register char *np;
        !           272:        extern struct passwd * getpwnam();
        !           273: 
        !           274:        if (strlen(asuser) > 0) {
        !           275:                if((pwp = getpwnam(asuser)) == NULL)
        !           276:                        merr("No such user %s.\n", asuser);
        !           277:                myuid = pwp -> pw_uid;
        !           278:        } else          
        !           279:                myuid = getuid();
        !           280:        if ((pwp = getpwuid(myuid)) == NULL)
        !           281:                merr("Who are you?\n");
        !           282:        np = pwp->pw_name;
        !           283:        mygid = pwp->pw_gid;
        !           284:        strcat(spoolname, np);
        !           285:        strcpy(myname, np);
        !           286:        strcpy(myfullname, pwp->pw_gecos);
        !           287:        strcpy(mymbox, pwp->pw_dir);
        !           288:        strcat(mymbox, "/mbox");
        !           289:        strcpy(mydead, pwp->pw_dir);
        !           290:        strcat(mydead, "/dead.letter");
        !           291:        strcpy(mysig, pwp->pw_dir);
        !           292:        strcat(mysig, "/.sig.mail");
        !           293:        strcpy(myalias, pwp->pw_dir);
        !           294:        strcat(myalias, "/.aliases");
        !           295:        mktemp(templ);
        !           296: 
        !           297:        if ((editname=getenv("EDITOR"))==NULL)
        !           298:                editname = "/bin/ed";
        !           299: 
        !           300:        if ( ((scatname=getenv("PAGER")) != NULL) &&
        !           301:             (strlen(scatname) == 0) )
        !           302:                scatname = NULL;
        !           303: 
        !           304:        if ((askcc=getenv("ASKCC")) != NULL)
        !           305:                if ( strcmp(askcc, "YES") )
        !           306:                        askcc = NULL;
        !           307: }
        !           308: 
        !           309: /*
        !           310:  * Process mail's interactive commands
        !           311:  * for reading/deleting/saving mail.
        !           312:  */
        !           313: commands()
        !           314: {
        !           315:        register struct msg *mp;
        !           316:        struct msg *dest;
        !           317:        register char **fnp;
        !           318:        register FILE *fp;
        !           319:        fsize_t seek;
        !           320: 
        !           321:        readmail();
        !           322:        mprint(mp = rflag ? m_last : m_first);
        !           323:        for (;;) {
        !           324:                readmail();
        !           325:                intcheck();
        !           326:                if ( ! pflag) {
        !           327:                        callmexmail = 0;
        !           328:                        mmsg("? ");
        !           329:                        if (fgets(cline, sizeof cline, stdin) == NULL) {
        !           330:                                if (intcheck())
        !           331:                                        continue;
        !           332:                                break;
        !           333:                        }
        !           334:                }
        !           335:                switch (cline[0]) {
        !           336:                case 'd':
        !           337:                        if (cline[1] != '\n')
        !           338:                                goto usage;
        !           339:                        mp->m_flag += 1;
        !           340:                        goto advance;
        !           341: 
        !           342:                case 'm':
        !           343:                case 't':
        !           344:                        if (csplit(cline, args) == 1) {
        !           345:                                /* We don't want to put anything into
        !           346:                                   args that we didn't get from malloc. */
        !           347: 
        !           348:                                if (args[1] != NULL) {
        !           349:                                        free(args[1]);
        !           350:                                }
        !           351:                                args[1] = malloc(strlen(myname) + 1);
        !           352:                                strcpy(args[1], myname);
        !           353:                                args[2] = NULL;
        !           354:                        }
        !           355:                        callmexmail = (cline[1] == 'x');
        !           356:                        if (cline[0] == 'm') {
        !           357:                                send2(mfp, args+1, mp->m_seek, mp->m_end - 3, 0);
        !           358:                                fseek(mfp, mp->m_seek, 0);
        !           359:                        } else
        !           360:                                send2(stdin, args+1, 0L, (fsize_t)MAXLONG, 1);
        !           361:                        break;
        !           362: 
        !           363:                case '.':
        !           364:                case 'p':
        !           365:                        if (cline[1] == 'x') {
        !           366:                                callmexmail = 1;
        !           367:                                if (cline[2] != '\n')
        !           368:                                        goto usage;
        !           369:                        } else if (cline[1] != '\n')
        !           370:                                goto usage;
        !           371:                        if (mprint(mp))
        !           372:                                break;
        !           373:                        goto advance;
        !           374: 
        !           375:                case 'q':
        !           376:                        if (cline[1] != '\n')
        !           377:                                goto usage;
        !           378:                        mquit();
        !           379:                        /* NOTREACHED */
        !           380: 
        !           381:                case 'r':
        !           382:                        if (cline[1] != '\n')
        !           383:                                goto usage;
        !           384:                        rflag = ! rflag;
        !           385:                        break;
        !           386:                case 's':
        !           387:                case 'w':
        !           388:                        if (csplit(cline, args) == 1) {
        !           389:                                /* We don't want to put anything into
        !           390:                                   args that we didn't get from malloc. */
        !           391: 
        !           392:                                if (args[1] != NULL) {
        !           393:                                        free(args[1]);
        !           394:                                }
        !           395:                                args[1] = malloc(strlen(mymbox) + 1);
        !           396:                                strcpy(args[1], mymbox);
        !           397:                                args[2] = NULL;
        !           398:                        }
        !           399:                        seek = mp->m_seek;
        !           400:                        if (cline[0] == 'w')
        !           401:                                seek += mp->m_hsize;
        !           402:                        for (fnp = &args[1]; *fnp != NULL; fnp++) {
        !           403:                                fp = NULL;
        !           404:                                if (maccess(*fnp) < 0
        !           405:                                 || (fp = fopen(*fnp, "a")) == NULL
        !           406:                                 || mcopy(mfp, fp, seek, mp->m_end, 0))
        !           407:                                        mmsg(nosave, *fnp);
        !           408:                                if (fp != NULL) {
        !           409:                                        fclose(fp);
        !           410:                                        chown(*fnp, myuid, mygid);
        !           411:                                }
        !           412:                        }
        !           413:                        break;
        !           414: 
        !           415:                case 'x':
        !           416:                        if (cline[1] != '\n')
        !           417:                                goto usage;
        !           418:                        rmexit(0);
        !           419:                        /* NOTREACHED */
        !           420: 
        !           421:                case '!':
        !           422:                        if (system(cline+1) == 127)
        !           423:                                mmsg("Try again\n");
        !           424:                        else
        !           425:                                mmsg("!\n");
        !           426:                        break;
        !           427: 
        !           428:                case '?':
        !           429:                        mmsg(isummary);
        !           430:                        break;
        !           431: 
        !           432:                case '-':
        !           433:                        if (cline[1] != '\n')
        !           434:                                goto usage;
        !           435:                        dest = rflag ? m_last : m_first;
        !           436:                        goto nextmsg;
        !           437: 
        !           438:                case '+':
        !           439:                        if (cline[1] != '\n')
        !           440:                                goto usage;
        !           441:                case '\n':
        !           442:                advance:
        !           443:                        dest = rflag ? m_first : m_last;
        !           444:                nextmsg:
        !           445:                        do {
        !           446:                                if (mp == dest) {
        !           447:                                        if (pflag)
        !           448:                                                return;
        !           449:                                        mmsg("No more messages.\n");
        !           450:                                        break;
        !           451:                                }
        !           452:                                mp = (dest==m_last) ? mp->m_next : mp->m_prev;
        !           453:                        } while (mprint(mp) == 0);
        !           454:                        break;
        !           455: 
        !           456:                default:
        !           457:                usage:
        !           458:                        mmsg(iusage);
        !           459:                        break;
        !           460:                }
        !           461:        }
        !           462:        putc('\n', stderr);
        !           463:        mquit();
        !           464: }
        !           465: 
        !           466: /*
        !           467:  * Read through the mail-box file
        !           468:  * constructing list of letters.
        !           469:  * On subsequent calls, append any additional mail
        !           470:  * and notify the user.
        !           471:  */
        !           472: readmail()
        !           473: {
        !           474:        register struct msg *mp;
        !           475:        struct stat sb;
        !           476:        static long m_last_end;
        !           477:        int datasw;
        !           478: 
        !           479:        if (m_first == NULL) {
        !           480:                if (stat(mailbox, &sb) < 0)
        !           481:                        merr(nombox, mailbox);
        !           482:                if (sb.st_size == 0)
        !           483:                        merr(nomail);
        !           484:                if (access(mailbox, AREAD) < 0)
        !           485:                        merr(noperm, mailbox);
        !           486:                if ((mfp = fopen(mailbox, "r")) == NULL)
        !           487:                        merr(moerr, mailbox);
        !           488:                m_last_end = 0;
        !           489:        } else {
        !           490:                fstat(fileno(mfp), &sb);
        !           491:                if (sb.st_size == m_last_end)
        !           492:                        return;
        !           493:                mmsg("More mail received.\n");
        !           494:        }
        !           495: 
        !           496:        for(mlock(myuid);;) {
        !           497:                fseek(mfp, m_last_end, 0);
        !           498:                datasw = 0;
        !           499:                while (fgets(msgline, sizeof msgline, mfp) != NULL) {
        !           500:                        /* NB: this means the implicit message
        !           501:                           seperator is actually "\n\1\1\n".  */
        !           502:                        if(!(datasw = strcmp("\1\1\n", msgline))) {
        !           503:                                /* message seperator */
        !           504:                                mp = (struct msg *)myalloc(sizeof(*mp));
        !           505:                                mp->m_next = NULL;
        !           506:                                mp->m_prev = m_last;
        !           507:                                mp->m_flag = mp->m_hsize = 0;
        !           508:                                mp->m_seek = m_last_end;
        !           509:                                mp->m_end = m_last_end = ftell(mfp);
        !           510:                                if (m_first == NULL)
        !           511:                                        m_last = m_first = mp;
        !           512:                                else
        !           513:                                        m_last = m_last->m_next = mp;
        !           514:                        }
        !           515:                }
        !           516: 
        !           517:                if(!datasw) /* data ended with message seperator */
        !           518:                        break;
        !           519: 
        !           520:                /* unterminated data, patch and retry */
        !           521:                fclose(mfp);
        !           522:                if ((mfp = fopen(mailbox, "a")) == NULL)
        !           523:                        merr(moerr, mailbox);
        !           524:                fprintf(mfp, "\1\1\n"); /* terminate it */
        !           525:                fclose(mfp);
        !           526:                if ((mfp = fopen(mailbox, "r")) == NULL)
        !           527:                        merr(moerr, mailbox);
        !           528:                mmsg("Incomplete message found.\n");
        !           529:        }
        !           530:        munlock();
        !           531: }
        !           532: 
        !           533: /*
        !           534:  * Lock the appropriately-numbered mailbox
        !           535:  * (numbered by user-number) from multiple
        !           536:  * accesses. There is a (small) race here
        !           537:  * which will be overlooked for now.
        !           538:  */
        !           539: char   *lockname;
        !           540: 
        !           541: mlock(uid)
        !           542: int uid;
        !           543: {
        !           544:        register int fd;
        !           545:        static char lock[32];
        !           546: 
        !           547:        lockname = lock;
        !           548:        sprintf(lock, "/tmp/maillock%d", uid);
        !           549:        while (access(lockname, 0) == 0)
        !           550:                sleep(1);
        !           551:        if ((fd = creat(lockname, 0)) >= 0)
        !           552:                close(fd);
        !           553: }
        !           554: 
        !           555: /*
        !           556:  * Unlock the currently-set lock (by `mlock')
        !           557:  * also called from rmexit.
        !           558:  */
        !           559: munlock()
        !           560: {
        !           561:        if (lockname != NULL)
        !           562:                unlink(lockname);
        !           563:        lockname = NULL;
        !           564: }
        !           565: 
        !           566: /*
        !           567:  * Exit, after rewriting the
        !           568:  * mailbox
        !           569:  */
        !           570: mquit()
        !           571: {
        !           572:        register struct msg *mp;
        !           573:        register FILE *nfp, *tmpfp;
        !           574:        struct stat sb;
        !           575: 
        !           576:        /* Get new stuff. */
        !           577:        readmail();
        !           578:        /* There is a slight race here.  We really should
        !           579:           lock BEFORE the readmail(), but readmail() does unlocks...
        !           580:           FIX ME. */
        !           581:        mlock(myuid);
        !           582: 
        !           583:        if (mailbox != spoolname && maccess(mailbox) < 0)
        !           584:                merr(noperm, mailbox);
        !           585:        fstat(fileno(mfp), &sb);
        !           586:        signal(SIGINT, SIG_IGN);
        !           587:        signal(SIGPIPE, SIG_IGN);
        !           588: 
        !           589:        /* Make a copy of the mail box; we're going to overwrite it.  */
        !           590:        tmpfp = tmp_copy(mfp);
        !           591:        fclose(mfp);
        !           592: 
        !           593:        if ((nfp = fopen(mailbox, "w")) == NULL)
        !           594:                merr("Cannot re-write '%s'\n", mailbox);
        !           595:        chown(mailbox, sb.st_uid, sb.st_gid);
        !           596:        chmod(mailbox, sb.st_mode&0777);
        !           597:        for (mp = m_first; mp != NULL; mp = mp->m_next) {
        !           598: 
        !           599:                if (mp->m_flag == 0) {
        !           600:                        if (mcopy(tmpfp, nfp, mp->m_seek, mp->m_end, 0)) {
        !           601:                                merr(wrerr, mailbox);
        !           602:                        }
        !           603:                } /* if (mp->m_flag == 0) */
        !           604: 
        !           605:        } /* for (walk through the linked list of messages) */
        !           606: 
        !           607:        fclose(nfp);
        !           608:        fclose(tmpfp);
        !           609:        munlock();
        !           610:        rmexit(0);
        !           611: }
        !           612: 
        !           613: /*
        !           614:  * Print the current message, given by
        !           615:  * the message pointer (`mp').
        !           616:  */
        !           617: mprint(mp)
        !           618: register struct msg *mp;
        !           619: {
        !           620:        FILE *xfp;
        !           621: 
        !           622:        if (mp->m_flag)
        !           623:                return 0;
        !           624:        if (callmexmail) {
        !           625:                if (scatname != NULL) 
        !           626:                        sprintf(cmdname, "xdecode | %s", scatname);
        !           627:                else
        !           628:                        sprintf(cmdname, "xdecode");
        !           629:                if ((xfp = popen(cmdname, "w")) == NULL)
        !           630:                        return 0;
        !           631:                mcopy(mfp, xfp, mp->m_seek+mp->m_hsize, mp->m_end, 1);
        !           632:                pclose(xfp);
        !           633:        } else {
        !           634:                fseek(mfp, mp->m_seek, 0);
        !           635:                if (fgets(msgline, sizeof msgline, mfp) != NULL &&
        !           636:                    strncmp(msgline, "From xmail", 10) == 0) {
        !           637:                        printf("From xmail\n");
        !           638:                        system("/usr/games/fortune");
        !           639:                        return(1);
        !           640:                }
        !           641:                if (scatname != NULL) {
        !           642:                        sprintf(cmdname, "%s", scatname);
        !           643:                        if ((xfp = popen(cmdname, "w")) == NULL)
        !           644:                                return(0);
        !           645:                        mcopy(mfp, xfp, mp->m_seek, mp->m_end - 3, 1);
        !           646:                        if ( ((pclose(xfp)>>8)&0xFF) == SIGINT )
        !           647:                                putc('\n', stdout);
        !           648:                } else {
        !           649:                        mcopy(mfp, stdout, mp->m_seek, mp->m_end - 3, 1);
        !           650:                }
        !           651:        }
        !           652:        return (1);
        !           653: }
        !           654: 
        !           655: /*
        !           656:  *     Get additional users to receive message (CC:)
        !           657:  */
        !           658: 
        !           659: char **
        !           660: getcc()
        !           661: {
        !           662:        static  char names[NCLINE];
        !           663:        static  char *ccargs[NARGS];
        !           664: 
        !           665:        ccargs[0] = NULL;
        !           666:        mmsg("CC: ");
        !           667:        if ( fgets(names, sizeof names, stdin) == NULL )
        !           668:                return(ccargs);
        !           669: 
        !           670:        csplit(names, ccargs);
        !           671:        return(ccargs);
        !           672: }
        !           673: 
        !           674:        
        !           675: /*
        !           676:  * Errors, usage, and exit removing
        !           677:  * any tempfiles left around.
        !           678:  */
        !           679: mmsg(x)
        !           680: {
        !           681:        fprintf(stderr, "%r", &x);
        !           682: }
        !           683: 
        !           684: merr(x, s)
        !           685: char *x, *s;
        !           686: {
        !           687:        mmsg(x, s);
        !           688:        logdump("merr: ");
        !           689:        logdump(x, s);
        !           690:        rmexit(1);
        !           691: }
        !           692: 
        !           693: rmexit(s)
        !           694: int s;
        !           695: {
        !           696:        if (temp != NULL)
        !           697:                unlink(temp);
        !           698:        munlock();
        !           699: 
        !           700:        logdump("About to exit, status = 0x%04x\n", s);
        !           701:        logclose();
        !           702: 
        !           703:        exit(s);
        !           704: }
        !           705: 
        !           706: /*
        !           707:  * Catch interrupts, taking the
        !           708:  * appropriate action based on
        !           709:  * the `-q' option.
        !           710:  */
        !           711: int    intrflag;               /* On when interrupt sent       */
        !           712: int    pipeflag;               /* On when broken pipe caught   */
        !           713: 
        !           714: catchintr()
        !           715: {
        !           716:        logdump("Caught SIGINT\n");
        !           717:        if (qflag)
        !           718:                rmexit(1);
        !           719:        intrflag = 1;
        !           720:        signal(SIGINT, catchintr);
        !           721: }
        !           722: 
        !           723: catchpipe()
        !           724: {
        !           725:        logdump("Caught SIGPIPE\n");
        !           726:        pipeflag = 1;
        !           727:        signal(SIGPIPE, catchpipe);
        !           728: }
        !           729: 
        !           730: intcheck()
        !           731: {
        !           732:        if (intrflag || pipeflag) {
        !           733:                if (intrflag)
        !           734:                        putc('\n', stdout);
        !           735:                intrflag = pipeflag = 0;
        !           736:                return (1);
        !           737:        }
        !           738:        return (0);
        !           739: }
        !           740: 
        !           741: /*
        !           742:  * Call the system to execute a command line
        !           743:  * which is passed as an argument.
        !           744:  * Change the user id and group id.
        !           745:  */
        !           746: system(line)
        !           747: char *line;
        !           748: {
        !           749:        int status, pid;
        !           750:        register wpid;
        !           751:        register int (*intfun)(), (*quitfun)();
        !           752: 
        !           753:        if ((pid = fork()) < 0)
        !           754:                return (-1);
        !           755:        if (pid == 0) {         /* Child */
        !           756:                setuid(myuid);
        !           757:                setgid(mygid);
        !           758:                execl("/bin/sh", "sh", "-c", line, NULL);
        !           759:                exit(0177);
        !           760:        }
        !           761:        intfun = signal(SIGINT, SIG_IGN);
        !           762:        quitfun = signal(SIGQUIT, SIG_IGN);
        !           763:        while ((wpid = wait(&status))!=pid && wpid>=0)
        !           764:                ;
        !           765:        if (wpid < 0)
        !           766:                status = wpid;
        !           767:        signal(SIGINT, intfun);
        !           768:        signal(SIGQUIT, quitfun);
        !           769:        return (status);
        !           770: }
        !           771: 
        !           772: char   *
        !           773: revnop()
        !           774: {
        !           775:        register        char *cp;
        !           776:        register        char c;
        !           777:        static          char revnobuf[32];
        !           778: 
        !           779:        if ((cp = index(rcsrev, ' ')) != NULL) {
        !           780:                while (((c = *++cp) == ' ') && (c != '\0'))
        !           781:                        ;
        !           782:                strcpy(revnobuf, cp);
        !           783:                if ((cp = index(revnobuf, ' ')) != NULL)
        !           784:                        *cp = '\0';
        !           785:                return (revnobuf);
        !           786:        } else
        !           787:                return("OOPS");
        !           788: }
        !           789: 
        !           790: /*
        !           791:  * Split a command line up into
        !           792:  * argv (passed) and argc (returned).
        !           793:  * We assume that elements of "args" are either NULL or they were
        !           794:  * returned from malloc, so that they can be freed.
        !           795:  */
        !           796: int
        !           797: csplit(command, args)
        !           798: char *command;
        !           799: char **args;
        !           800: {
        !           801:        register char *cp;
        !           802:        int i, argsize;
        !           803: 
        !           804:        i = 0; /* Start filling in at the zero'th arg.  */
        !           805:        cp = eat_ws(command);   
        !           806: 
        !           807:        /* Walk "cp" through "command", copying segments as we go.  */
        !           808:        while ( *cp != CNULL ) {
        !           809:                /* We've found an argument; find some space.  */
        !           810:                if (args[i] != NULL ) {
        !           811:                        free(args[i]);
        !           812:                }
        !           813: 
        !           814:                /* Figure out how big the argment is.  */
        !           815:                argsize = (int) (find_ws(cp) - cp);
        !           816: 
        !           817:                /* Alloc enough space for it--include the trailing NULL.  */
        !           818:                if ((args[i] = malloc(argsize + 1)) == NULL) {
        !           819:                        mmsg(allocerr, "csplit");
        !           820:                        return(0);  /* Is this the approriate action?? */
        !           821:                }
        !           822: 
        !           823:                /* Copy the argument into the space.  */
        !           824:                memcpy(args[i], cp, argsize);
        !           825:                args[i][argsize] = CNULL; /* This may be redundant.  */
        !           826: 
        !           827:                /* Make sure that cp points to after the argument.  */
        !           828:                cp += argsize;
        !           829: 
        !           830:                cp = eat_ws(cp);
        !           831:                ++i;
        !           832:        } /* while (walk "cp" through "command") */
        !           833: 
        !           834:        args[i] = NULL;
        !           835:        return (i);
        !           836: }
        !           837: 
        !           838: /*
        !           839:  * Find the next occurence of non-white space in character string s.
        !           840:  */
        !           841: char *
        !           842: eat_ws(s)
        !           843:        char *s;
        !           844: {
        !           845:        while(isspace(*s)){
        !           846:                ++s;
        !           847:        }
        !           848:        return(s);
        !           849: }
        !           850: 
        !           851: /*
        !           852:  * Find next occurence of white space in character string s.
        !           853:  */
        !           854: char *
        !           855: find_ws(s)
        !           856:        register char *s;
        !           857: {
        !           858:        while((*s != CNULL) && !isspace(*s) ){
        !           859:                ++s;
        !           860:        }
        !           861:        return(s);
        !           862: }      

unix.superglobalmegacorp.com

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