Annotation of coherent/d/bin/msgs.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     msgs - system wide messages program
                      3:  */
                      4: 
                      5: #include <stdio.h>
                      6: #include <sys/stat.h>
                      7: #include <sys/dir.h>
                      8: #include <ctype.h>
                      9: #include <signal.h>
                     10: 
                     11: #define BSIZE 512
                     12: #define NLINE 512
                     13: #define PAGELEN 20
                     14: 
                     15: char   mline[NLINE];   /* line of mail file */
                     16: 
                     17: int    qflag;          /* query new messages */
                     18: int    msgsnum;        /* command line numeric argument */
                     19: int    exstat;         /* exit status */
                     20: 
                     21: FILE   *boundfp;               /* file pointer for boundname */
                     22: char   *boundformat = "LOWMSG=%d\tHIGHMSG=%d\n";
                     23: unsigned int   lowmsg;         /* lowest number message in msgsdir */
                     24: unsigned int   highmsg;        /* highest number message in msgsdir */
                     25: 
                     26: FILE   *mailfp;                /* file pointer to mailfile */
                     27: char   *mailfile = "/usr/spool/mail/msgs";
                     28: char   *msgsdir  = "/usr/msgs";
                     29: char   *rcname = ".msgsrc";
                     30: char   *rcformat = "MSGSNUM=%d\n";
                     31: char   *boundname = "/usr/msgs/bounds";
                     32: char   *home;
                     33: char   *scatname;
                     34: 
                     35: #define        FATAL           1       /* used by badmsg() */
                     36: #define NONFATAL       0
                     37: 
                     38: extern char *getenv();
                     39: 
                     40: main(argc, argv)
                     41: int argc;
                     42: char *argv[];
                     43: {
                     44:        int rcnum, num;
                     45: 
                     46:        if ( argc > 1 )
                     47:                doargs(argc, argv);
                     48:        dobounds();
                     49:        readmail();
                     50:        rcnum = readrc();
                     51:        num = (msgsnum<=0) ? rcnum+msgsnum : msgsnum;
                     52:        if ( (num=domsgs(num)) > rcnum )
                     53:                writerc(num);   
                     54:        exit(exstat);
                     55: }
                     56: 
                     57: /*
                     58:  *     Fix the boundname file and set the global variables
                     59:  *     lowmsg and highmsg to the appropriate values.
                     60:  */
                     61: 
                     62: dobounds()
                     63: {
                     64:        struct stat st;
                     65: 
                     66:        if ( stat(boundname, &st) < 0 ) {
                     67:                calcbounds();
                     68:                return;
                     69:        }
                     70: 
                     71:        if ( (boundfp=fopen(boundname,"rw")) == NULL )
                     72:                badmsg(FATAL, "Can't open read/write: %s", boundname);
                     73: 
                     74:        if ( fscanf(boundfp, boundformat, &lowmsg, &highmsg) != 2 )
                     75:                calcbounds();
                     76: }
                     77: 
                     78: /*
                     79:  *     Recreate the boundname file
                     80:  */
                     81: 
                     82: calcbounds()
                     83: {
                     84:        int dirfd;
                     85:        char buf[BSIZE];
                     86:        int num, size;
                     87:        struct direct *dentry;
                     88: 
                     89:        if ( (boundfp=fopen(boundname,"w")) == NULL )
                     90:                badmsg(FATAL, "Can't open: %s", boundname);
                     91: 
                     92:        if ( chmod(boundname, 0666) < 0 )
                     93:                badmsg(FATAL, "Can't chmod: %s", boundname);
                     94: 
                     95:        if ( (dirfd=open(msgsdir, 0)) < 0 )
                     96:                badmsg(FATAL, "Can't open: %s", msgsdir);
                     97: 
                     98:        highmsg = 0;
                     99:        lowmsg = ~000;
                    100: 
                    101:        while ( (size=read(dirfd, buf, BSIZE)) != 0 ) {
                    102:                dentry = (struct direct *) buf;
                    103:                while ( (size-=sizeof(struct direct)) >= 0 ) {
                    104:                        
                    105:                        if ( dentry->d_ino &&
                    106:                                 (num=decode(dentry->d_name)) > 0 ) {
                    107:                                if ( num > highmsg )
                    108:                                        highmsg = num;
                    109:                                if ( num < lowmsg )
                    110:                                        lowmsg = num;
                    111:                        }
                    112:                        dentry++;
                    113:                }
                    114:        }
                    115: 
                    116:        if ( highmsg==0 )
                    117:                lowmsg = 0;
                    118: 
                    119:        fprintf(boundfp, boundformat, lowmsg, highmsg);
                    120: }
                    121: 
                    122: /*
                    123:  *     Does an atoi of the given string once it is certain that
                    124:  *     it is all digits.
                    125:  */
                    126: 
                    127: decode(str)
                    128: char *str;
                    129: {
                    130:        register int i;
                    131: 
                    132:        for (i=0; i<DIRSIZ; i++) {
                    133:                if ( str[i] == '\0' )
                    134:                        break;
                    135:                if ( i==0 && str[0] == '-' )
                    136:                        continue;
                    137:                if ( !isascii(str[i]) || !isdigit(str[i]) )
                    138:                        return(0);
                    139:        }
                    140: 
                    141:        return(atoi(str));
                    142: }
                    143: 
                    144: /*
                    145:  *     Process the mail in mailfile, and put it in the msgsdir.
                    146:  */
                    147: 
                    148: readmail()
                    149: {
                    150:        struct stat st;
                    151:        int fd;
                    152: 
                    153:        if ( stat(mailfile, &st) < 0 ) {
                    154:                badmsg(NONFATAL,"Can't stat: %s", mailfile);
                    155:                return;
                    156:        }
                    157: 
                    158:        if ( st.st_size == 0 ) {
                    159:                fclose(boundfp);
                    160:                return;
                    161:        }
                    162: 
                    163:        if ( (mailfp=fopen(mailfile, "rw")) == NULL ) {
                    164:                badmsg(NONFATAL,"Can't open read/write: %s", mailfile);
                    165:                return;
                    166:        }
                    167: 
                    168:        if ( chdir(msgsdir) < 0 )
                    169:                badmsg(FATAL, "Can't chdir: %s", msgsdir);
                    170: 
                    171:        while ( dumpmsg() ) ;
                    172:        
                    173:        fclose(mailfp);
                    174:        if ( (fd=creat(mailfile, 0644)) < 0 )
                    175:                badmsg(FATAL, "Can't creat: %s", mailfile);
                    176:        close(fd);
                    177: 
                    178:        rewind(boundfp);
                    179:        fprintf(boundfp, boundformat, lowmsg, highmsg);
                    180:        fclose(boundfp);
                    181: }
                    182: 
                    183: /*
                    184:  *     Dump the current message from the mailfile into the msgsdir
                    185:  */
                    186: 
                    187: dumpmsg()
                    188: {
                    189:        char *tmp;
                    190:        char numname[10];
                    191:        FILE *fp;
                    192: 
                    193:        while ( (tmp=fgets(mline, NLINE, mailfp)) != NULL )
                    194:                if ( strcmp(mline, "\1\1\n") )
                    195:                        break;
                    196: 
                    197:        if ( tmp == NULL )
                    198:                return(0);
                    199: 
                    200:        sprintf(numname, "%d", ++highmsg);
                    201: 
                    202:        if ( (fp=fopen(numname,"w")) == NULL )
                    203:                badmsg(FATAL, "Can't open to write: %s/%s", msgsdir, numname);
                    204: 
                    205:        do {
                    206:                fputs(mline, fp);
                    207:                if ( strcmp(mline, "\1\1\n") == 0 )
                    208:                        break;
                    209:        } while ( fgets(mline, NLINE, mailfp) != NULL );
                    210: 
                    211:        fclose(fp);
                    212:        if ( lowmsg == 0 )
                    213:                lowmsg = 1;
                    214:        return(1);
                    215: }
                    216:        
                    217: /*
                    218:  *     Display the messages in msgsdir beginning with
                    219:  *     message number (num)
                    220:  */
                    221:        
                    222: domsgs(num)
                    223: int num;
                    224: {
                    225:        int intexit();
                    226: 
                    227:        signal(SIGINT, intexit);
                    228:        signal(SIGPIPE, intexit);
                    229:        
                    230:        if ( chdir(msgsdir) < 0 )
                    231:                badmsg(FATAL, "Can't chdir: %s", msgsdir);
                    232:        
                    233:        if ( num < 1  || num < lowmsg )
                    234:                num = lowmsg;
                    235: 
                    236:        if ( qflag ) {
                    237:                if (num <= highmsg) 
                    238:                        printf("There are new messages.\n");
                    239:                else
                    240:                        printf("No new messages.\n");
                    241:                return(num);
                    242:        }
                    243: 
                    244:        if ( ((scatname=getenv("PAGER")) != NULL) &&
                    245:             (strlen(scatname) == 0) )
                    246:                scatname = NULL;
                    247: 
                    248:        while ( num <= highmsg ) {
                    249:                if (do_one(num) < 0)
                    250:                        break;
                    251:                num += 1;
                    252:        }
                    253:                
                    254:        return(num);
                    255: }
                    256: 
                    257: /* 
                    258:  *     Display a single message, return (-1) if user
                    259:  *     requests to quit.
                    260:  */
                    261: 
                    262: do_one(num)
                    263: int num;
                    264: {
                    265:        FILE *fp;
                    266:        char numname[10];
                    267:        char ch, inputchar();
                    268:        long offset = 0;
                    269:        int newnum;
                    270:        struct stat st;
                    271: 
                    272:        sprintf(numname, "%d", num);
                    273: 
                    274:        if ( stat(numname, &st) < 0 )
                    275:                return(0);
                    276: 
                    277:        if ( (fp=fopen(numname, "r")) == NULL ) 
                    278:                return(0);
                    279: 
                    280:        printf("\nMessage Number %d [%ld chars]\n", num, st.st_size);
                    281: 
                    282:        while ( fgets(mline, NLINE, fp) != NULL ) {
                    283:                if ( (strncmp(mline, "Date: ", 6) == 0) ||
                    284:                     (strncmp(mline, "From: ", 6) == 0) ||
                    285:                     (strncmp(mline, "To: ", 4  ) == 0) ||
                    286:                     (strncmp(mline, "cc: ", 4  ) == 0) ||
                    287:                     havesubject() ) {
                    288:                        printf("%s", mline);
                    289:                        offset = ftell(fp);
                    290:                        continue;
                    291:                }
                    292:                if (offset)
                    293:                        break;
                    294:        }
                    295: 
                    296:        if ( !offset ) {
                    297:                fclose(fp);
                    298:                return(0);
                    299:        }
                    300:        fseek(fp, offset, 0);
                    301: 
                    302:        switch( ch=inputchar() ) {
                    303:        case 'Y':
                    304:                dumpit(fp);
                    305:        case 'N':
                    306:                fclose(fp);
                    307:                return(0);
                    308:        case 'Q':
                    309:                fclose(fp);
                    310:                return(-1);
                    311:        default:
                    312:                ungetc(ch, stdin);
                    313:                scanf("%d", &newnum);
                    314:                while ( getchar() != '\n' ) ;
                    315:                break;
                    316:        case '-':
                    317:                newnum = num - 1;
                    318:                break;
                    319:        }
                    320:        fclose(fp);
                    321:        if ( do_one(newnum) < 0 )
                    322:                return(-1);
                    323:        return(do_one(num));
                    324: }
                    325: 
                    326: /*
                    327:  *     Determine if we have a subject in mline.
                    328:  */
                    329: 
                    330: havesubject()
                    331: {
                    332:        static char *subject="subject:";
                    333:        register char *x = subject;
                    334:        register char *y = mline;
                    335: 
                    336:        while ( *x )
                    337:                if ( tolower(*y++)!=*x++ )
                    338:                        return(0);
                    339: 
                    340:        return(1);
                    341: }
                    342: 
                    343: /*
                    344:  *     Print out the text of the message in a scat like
                    345:  *     manner.
                    346:  */
                    347: 
                    348: dumpit(fp)
                    349: FILE *fp;
                    350: {
                    351:        FILE *xfp;
                    352:        char ch, *cmdname;
                    353: 
                    354:        if ( scatname != NULL ) {
                    355:                sprintf(cmdname=&mline[0], "%s", scatname);
                    356:                if ( (xfp=popen(cmdname, "w")) == NULL )
                    357:                        badmsg(FATAL, "Can't open pipe for writing: %s",
                    358:                                                                 cmdname);
                    359:                while ( (ch=getc(fp)) != EOF )
                    360:                        if ( putc(ch, xfp) == EOF )
                    361:                                intexit(SIGPIPE);
                    362:                if ( ((pclose(xfp)>>8)&0xFF) == SIGINT )
                    363:                        intexit(SIGINT);
                    364:        } else {
                    365:                while ( (ch=getc(fp)) != EOF )
                    366:                        putc(ch, stdout);
                    367:        }
                    368: }
                    369: 
                    370: intexit(status)
                    371: {
                    372:        putc('\n', stdout);
                    373:        _exit(status);
                    374: }
                    375: 
                    376: char
                    377: inputchar()
                    378: {
                    379:        char ch;
                    380: 
                    381:        for (;;) {
                    382:                printf("[ynq]: ");
                    383:                while ( (ch=getchar()) == ' ' || ch == '\t' ) ;
                    384:                if ( isalpha(ch) )
                    385:                        ch = toupper(ch);
                    386: 
                    387:                if ( ch == '\n' )
                    388:                        return('Y');
                    389: 
                    390:                if ( isdigit(ch) )
                    391:                        return(ch);
                    392: 
                    393:                while (getchar() != '\n') ;
                    394: 
                    395:                if ( ch == 'N' || ch == 'Y' || ch == 'Q' || ch == '-')
                    396:                        return(ch);
                    397:        }
                    398: }
                    399:        
                    400: /*
                    401:  *     Returns the next message number to read according the the
                    402:  *     file (.msgsrc) in the HOME directory.  Returns message
                    403:  *     number (1) if any problems.
                    404:  */
                    405: 
                    406: readrc()
                    407: {
                    408:        FILE *msgsrc;
                    409:        struct stat st;
                    410:        int num;
                    411: 
                    412:        if ( (home=getenv("HOME")) == NULL ) {
                    413:                badmsg(NONFATAL,"No HOME variable in environment.");
                    414:                return(1);
                    415:        }
                    416: 
                    417:        if ( chdir(home) < 0 ) {
                    418:                badmsg(NONFATAL,"Can't chdir to %s", home);
                    419:                return(1);
                    420:        }
                    421: 
                    422:        if ( stat(rcname, &st) < 0 )
                    423:                return(1);
                    424: 
                    425:        if ( (msgsrc=fopen(rcname,"r")) == NULL ) {
                    426:                badmsg(NONFATAL, "Can't open to read: %s/%s", home, rcname);
                    427:                return(1);
                    428:        }
                    429: 
                    430:        if ( fscanf(msgsrc, rcformat, &num) != 1 ) {
                    431:                badmsg(NONFATAL, "Badly formatted file: %s/%s", home, rcname);
                    432:                return(1);
                    433:        }
                    434: 
                    435:        fclose(msgsrc);
                    436:        return(num);
                    437: }
                    438: 
                    439: /*
                    440:  *     Update the rcname file in the user's home directory.
                    441:  */
                    442: 
                    443: writerc(num)
                    444: int num;
                    445: {
                    446:        FILE *msgsrc;
                    447: 
                    448:        if ( chdir(home) < 0 )
                    449:                badmsg(FATAL,"Can't chdir to %s", home);
                    450: 
                    451:        if (setuid(getuid())< 0)
                    452:                badmsg(FATAL, "Can't setuid to %d\n", getuid());
                    453: 
                    454:        if ( (msgsrc=fopen(rcname,"w")) == NULL )
                    455:                badmsg(FATAL, "Can't open to write: %s/%s", home, rcname);
                    456: 
                    457:        fprintf(msgsrc, rcformat, num);
                    458:        fclose(msgsrc);
                    459: }
                    460: 
                    461: /*
                    462:  *     Process command line arguments.
                    463:  */
                    464: 
                    465: doargs(argc, argv)
                    466: register int argc;
                    467: register char *argv[];
                    468: {
                    469:        if ( argc > 2 )
                    470:                usage();
                    471: 
                    472:        if ( strcmp(argv[1], "-q") == 0 )
                    473:                qflag = 1;
                    474:        else if ( (msgsnum=decode(argv[1])) == 0 )
                    475:                usage();
                    476: }
                    477: 
                    478: /*
                    479:  *     Issue error message.  flag is either NONFATAL or FATAL
                    480:  */
                    481: 
                    482: badmsg(flag, x)
                    483: int flag;
                    484: char *x;
                    485: {
                    486:        fprintf(stderr, "msgs: %r\n", &x);
                    487:        if ( flag == FATAL)
                    488:                exit(1);
                    489:        else
                    490:                exstat = 1;
                    491: }
                    492:        
                    493: char *usemsg = "\n\
                    494: Usage:   msgs [ -q ] [ number ]\n\
                    495:         -q    :  query existence of new messages\n\
                    496:         number:  greater than zero, start with that message number\n\
                    497:                  less than zero, start backward that many from current\n\n";
                    498: 
                    499: usage()
                    500: {
                    501:        fprintf(stderr, usemsg);
                    502:        exit(1);
                    503: }
                    504: 

unix.superglobalmegacorp.com

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