Annotation of researchv10dc/cmd/news.c.O, revision 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.