Annotation of researchv10dc/cmd/news.c.O, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     news foo        prints /usr/news/foo
                      3:  *     news -a         prints all news items, latest first
                      4:  *     news -n         lists names of new items
                      5:  *     news -s         tells count of new items only
                      6:  *     news            prints items changed since last news
                      7:  */
                      8: 
                      9: #include <stdio.h>
                     10: #include <sys/types.h>
                     11: #include <sys/stat.h>
                     12: #include <setjmp.h>
                     13: #include <signal.h>
                     14: #include <sys/dir.h>
                     15: #include <pwd.h>
                     16: 
                     17: /* The number of leading spaces on each line of output */
                     18: #define INDENT 3
                     19: 
                     20: /* The maximum number of spaces to keep together, without trying to tab */
                     21: #define MAXSP 2
                     22: 
                     23: /*
                     24:  *     The following items should not be printed.
                     25:  */
                     26: char *ignore[] = {
                     27:        "core",
                     28:        "dead.letter",
                     29:        NULL
                     30: };
                     31: 
                     32: struct n_file {
                     33:        long n_time;
                     34:        char n_name[DIRSIZ];
                     35: } *n_list;
                     36: 
                     37: char NEWS[] = "/usr/news";
                     38: 
                     39: int n_count;
                     40: char stdbuf[BUFSIZ];
                     41: 
                     42: jmp_buf        save_addr;
                     43: 
                     44: main (argc, argv)
                     45:        int argc;
                     46:        char **argv;
                     47: {
                     48:        int print_item(), notify(), count();
                     49: 
                     50:        setbuf (stdout, stdbuf);
                     51:        initialize();
                     52:        read_dir();
                     53:        if (argc <= 1)
                     54:                late_news (print_item, 1);
                     55:        else if (       argc == 2 && argv[1][0] == '-'
                     56:            && argv[1][1] != '\0' && argv[1][2] == '\0')
                     57:                switch (argv[1][1]) {
                     58:                case 'a':
                     59:                        all_news();
                     60:                        break;
                     61: 
                     62:                case 'n':
                     63:                        late_news (notify, 0);
                     64:                        break;
                     65: 
                     66:                case 's':
                     67:                        late_news (count, 0);
                     68:                        break;
                     69: 
                     70:                default:
                     71:                        fprintf (stderr, "news: bad option %s\n", argv[1]);
                     72:                        exit (1);
                     73:                }
                     74:        else {
                     75:                int i;
                     76:                for (i=1; i<argc; i++)
                     77:                        print_item (argv[i]);
                     78:        }
                     79:        return 0;
                     80: }
                     81: 
                     82: /*
                     83:  *     read_dir: get the file names and modification dates for the
                     84:  *     files in /usr/news into n_list; sort them in reverse by
                     85:  *     modification date. We assume /usr/news is the working directory.
                     86:  */
                     87: 
                     88: read_dir()
                     89: {
                     90:        struct direct nf;
                     91:        struct stat sbuf;
                     92:        char fname[50];
                     93:        FILE *fd;
                     94:        int i, j;
                     95:        char *malloc(), *realloc();
                     96: 
                     97:        /* Open the current directory */
                     98:        if ((fd = fopen (".", "r")) == NULL) {
                     99:                fprintf (stderr, "news: ");
                    100:                perror (NEWS);
                    101:                exit (1);
                    102:        }
                    103: 
                    104:        /* Read the file names into n_list */
                    105:        n_count = 0;
                    106:        while (fread ((char *) &nf, sizeof nf, 1, fd) == 1) {
                    107:                strncpy (fname, nf.d_name, DIRSIZ);
                    108:                if (nf.d_ino != 0 && stat (fname, &sbuf) >= 0
                    109:                 && (sbuf.st_mode & S_IFMT) == S_IFREG) {
                    110:                        register char **p;
                    111:                        p = ignore;
                    112:                        while (*p && strncmp (*p, nf.d_name, DIRSIZ))
                    113:                                ++p;
                    114:                        if (!*p) {
                    115:                                if (n_count++ > 0)
                    116:                                        n_list = (struct n_file *)
                    117:                                                realloc ((char *) n_list,
                    118:                                                (unsigned)
                    119:                                                (sizeof (struct n_file)
                    120:                                                    * n_count));
                    121:                                else
                    122:                                        n_list = (struct n_file *) malloc
                    123:                                                ((unsigned)
                    124:                                                (sizeof (struct n_file) *
                    125:                                                n_count));
                    126:                                if (n_list == NULL) {
                    127:                                        fprintf (stderr, "news: no storage\n");
                    128:                                        exit (1);
                    129:                                }
                    130:                                n_list[n_count-1].n_time = sbuf.st_mtime;
                    131:                                strncpy (n_list[n_count-1].n_name,
                    132:                                        nf.d_name, DIRSIZ);
                    133:                        }
                    134:                }
                    135:        }
                    136: 
                    137:        /* Sort the elements of n_list in decreasing time order */
                    138:        for (i=1; i<n_count; i++)
                    139:                for (j=0; j<i; j++)
                    140:                        if (n_list[j].n_time < n_list[i].n_time) {
                    141:                                struct n_file temp;
                    142:                                temp = n_list[i];
                    143:                                n_list[i] = n_list[j];
                    144:                                n_list[j] = temp;
                    145:                        }
                    146: 
                    147:        /* Clean up */
                    148:        fclose (fd);
                    149: }
                    150: 
                    151: initialize()
                    152: {
                    153:        extern _exit();
                    154:        if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
                    155:                signal (SIGQUIT, _exit);
                    156:        umask (022);
                    157:        if (chdir (NEWS) < 0) {
                    158:                fprintf (stderr, "news: ");
                    159:                perror (NEWS);
                    160:                exit (1);
                    161:        }
                    162: }
                    163: 
                    164: all_news()
                    165: {
                    166:        int i;
                    167: 
                    168:        for (i=0; i<n_count; i++)
                    169:                print_item (n_list[i].n_name);
                    170: }
                    171: 
                    172: print_item (f)
                    173:        char *f;
                    174: {
                    175:        FILE *fd;
                    176:        char fname[DIRSIZ+1];
                    177:        static int firstitem = 1;
                    178:        int onintr();
                    179:        struct passwd *getpwuid();
                    180: 
                    181:        if (f == NULL) {
                    182:                return;
                    183:        }
                    184:        strncpy (fname, f, DIRSIZ);
                    185:        fname[DIRSIZ] = '\0';
                    186:        if ((fd = fopen (fname, "r")) == NULL) {
                    187:                fprintf (stderr, "news: %s/", NEWS);
                    188:                perror (fname);
                    189:        } else {
                    190:                register int c, ip, op;
                    191:                struct stat sbuf;
                    192:                char *ctime();
                    193:                struct passwd *pw;
                    194: 
                    195:                fstat (fileno (fd), &sbuf);
                    196:                if (firstitem) {
                    197:                        firstitem = 0;
                    198:                        putchar ('\n');
                    199:                }
                    200:                if (setjmp(save_addr))
                    201:                        goto finish;
                    202:                if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                    203:                        signal(SIGINT, onintr);
                    204:                printf ("%s ", fname);
                    205:                pw = getpwuid (sbuf.st_uid);
                    206:                if (pw)
                    207:                        printf ("(%s)", pw->pw_name);
                    208:                else
                    209:                        printf (".....");
                    210:                printf (" %s\n", ctime (&sbuf.st_mtime));
                    211: 
                    212:                /*
                    213:                 *      copy the news item to the standard output
                    214:                 *
                    215:                 *      ip is the output character position corresponding
                    216:                 *      to the present input character.  op is the
                    217:                 *      actual current output character position.
                    218:                 */
                    219:                op = 0;
                    220:                ip = INDENT;
                    221:                while ((c = getc (fd)) != EOF) {
                    222:                        switch (c) {
                    223: 
                    224:                        case '\r':
                    225:                        case '\n':
                    226:                                putchar (c);
                    227:                                op = 0;
                    228:                                ip = INDENT;
                    229:                                break;
                    230: 
                    231:                        case ' ':
                    232:                                ip++;
                    233:                                break;
                    234: 
                    235:                        case '\b':
                    236:                                if (ip > INDENT)
                    237:                                        ip--;
                    238:                                break;
                    239: 
                    240:                        case '\t':
                    241:                                ip = ((ip - INDENT + 8) & -8) + INDENT;
                    242:                                break;
                    243: 
                    244:                        default:
                    245:                                /*
                    246:                                 *      emit characters to get the output
                    247:                                 *      to the position that corresponds
                    248:                                 *      to this input character.
                    249:                                 *
                    250:                                 *      first, backspace if necessary
                    251:                                 */
                    252:                                while (ip < op) {
                    253:                                        putchar ('\b');
                    254:                                        op--;
                    255:                                }
                    256: 
                    257:                                /*
                    258:                                 *      send tabs to get close to the right
                    259:                                 *      place.  arrange to leave suitably
                    260:                                 *      small number of spaces as such.
                    261:                                 */
                    262:                                if (ip - op > MAXSP) {
                    263:                                        while ((op & -8) < (ip & -8)) {
                    264:                                                putchar ('\t');
                    265:                                                op = (op + 8) & -8;
                    266:                                        }
                    267:                                }
                    268: 
                    269:                                /* send spaces for fine-tuning */
                    270:                                while (ip > op) {
                    271:                                        putchar (' ');
                    272:                                        op++;
                    273:                                }
                    274: 
                    275:                                /* now ip == op */
                    276:                                putchar (c);
                    277:                                ip++;
                    278:                                op++;
                    279:                                break;
                    280:                        }
                    281:                }
                    282:                fflush (stdout);
                    283: finish:
                    284:                putchar ('\n');
                    285:                fclose (fd);
                    286:                if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                    287:                        signal(SIGINT, SIG_DFL);
                    288:        }
                    289: }
                    290: 
                    291: late_news (emit, update)
                    292:        int (*emit)(), update;
                    293: {
                    294:        long cutoff;
                    295:        int i;
                    296:        char fname[50], *getenv(), *cp;
                    297:        struct stat newstime;
                    298:        int fd;
                    299:        struct {
                    300:                long actime, modtime;
                    301:        } utb;
                    302: 
                    303:        /* Determine the time when last called */
                    304:        cp = getenv ("HOME");
                    305:        if (cp == NULL) {
                    306:                fprintf (stderr, "news: cannot find HOME variable\n");
                    307:                exit (1);
                    308:        }
                    309:        strcpy (fname, cp);
                    310:        strcat (fname, "/");
                    311:        strcat (fname, ".news_time");
                    312:        cutoff = stat (fname, &newstime) < 0? 0: newstime.st_mtime;
                    313: 
                    314:        /* Print the recent items */
                    315:        for (i=0; i<n_count && n_list[i].n_time > cutoff; i++)
                    316:                (*emit) (n_list[i].n_name);
                    317:        (*emit) ((char *) NULL);
                    318:        fflush (stdout);
                    319: 
                    320:        if (update) {
                    321:                /* Re-create the file and refresh the update time */
                    322:                if (n_count > 0 && (fd = creat (fname, 0666)) >= 0) {
                    323:                        utb.actime = utb.modtime = n_list[0].n_time;
                    324:                        close (fd);
                    325:                        utime (fname, &utb);
                    326:                }
                    327:        }
                    328: }
                    329: 
                    330: notify (s)
                    331:        char *s;
                    332: {
                    333:        static int first = 1;
                    334: 
                    335:        if (s) {
                    336:                if (first) {
                    337:                        first = 0;
                    338:                        printf ("news:", NEWS);
                    339:                }
                    340:                printf (" %.14s", s);
                    341:        } else if (!first)
                    342:                putchar ('\n');
                    343: }
                    344: 
                    345: /*ARGSUSED*/
                    346: count (s)
                    347:        char *s;
                    348: {
                    349:        static int nitems = 0;
                    350: 
                    351:        if (s)
                    352:                nitems++;
                    353:        else if (nitems) {
                    354:                printf ("%d news item", nitems);
                    355:                if (nitems > 1)
                    356:                        putchar ('s');
                    357:                printf (".\n");
                    358:        }
                    359: 
                    360: }
                    361: 
                    362: onintr()
                    363: {
                    364:        sleep(2);
                    365:        longjmp(save_addr, 1);
                    366: }

unix.superglobalmegacorp.com

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