Annotation of coherent/d/bin/mail/usermail/mail.c, revision 1.1.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.