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

unix.superglobalmegacorp.com

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