123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- /*
- * news foo prints /lib/news/foo
- * news -a prints all news items, latest first
- * news -n lists names of new items
- * news prints items changed since last news
- */
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #define NINC 50 /* Multiples of directory allocation */
- char NEWS[] = "/lib/news";
- char TFILE[] = "%s/lib/newstime";
- /*
- * The following items should not be printed.
- */
- char* ignore[] =
- {
- "core",
- "dead.letter",
- 0
- };
- typedef
- struct
- {
- int32_t time;
- char *name;
- int64_t length;
- } File;
- File* n_list;
- int n_count;
- int n_items;
- Biobuf bout;
- int fcmp(const void *a, const void *b);
- void read_dir(int update);
- void print_item(char *f);
- void eachitem(void (*emit)(char*), int all, int update);
- void note(char *s);
- void
- main(int argc, char *argv[])
- {
- int i;
- Binit(&bout, 1, OWRITE);
- if(argc == 1) {
- eachitem(print_item, 0, 1);
- exits(0);
- }
- ARGBEGIN{
- case 'a': /* print all */
- eachitem(print_item, 1, 0);
- break;
- case 'n': /* names only */
- eachitem(note, 0, 0);
- if(n_items)
- Bputc(&bout, '\n');
- break;
- default:
- fprint(2, "news: bad option %c\n", ARGC());
- exits("usage");
- }ARGEND
- for(i=0; i<argc; i++)
- print_item(argv[i]);
- exits(0);
- }
- int
- fcmp(const void *a, const void *b)
- {
- int32_t x;
- x = ((File*)b)->time - ((File*)a)->time;
- if(x < 0)
- return -1;
- if(x > 0)
- return 1;
- return 0;
- }
- /*
- * read_dir: get the file names and modification dates for the
- * files in /usr/news into n_list; sort them in reverse by
- * modification date.
- */
- void
- read_dir(int update)
- {
- Dir *d;
- char newstime[100], *home;
- int i, j, n, na, fd;
- n_count = 0;
- n_list = malloc(NINC*sizeof(File));
- na = NINC;
- home = getenv("home");
- if(home) {
- sprint(newstime, TFILE, home);
- d = dirstat(newstime);
- if(d != nil) {
- n_list[n_count].name = strdup("");
- n_list[n_count].time =d->mtime-1;
- n_list[n_count].length = 0;
- n_count++;
- free(d);
- }
- if(update) {
- fd = create(newstime, OWRITE, 0644);
- if(fd >= 0)
- close(fd);
- }
- }
- fd = open(NEWS, OREAD);
- if(fd < 0) {
- fprint(2, "news: ");
- perror(NEWS);
- exits(NEWS);
- }
- n = dirreadall(fd, &d);
- for(i=0; i<n; i++) {
- for(j=0; ignore[j]; j++)
- if(strcmp(ignore[j], d[i].name) == 0)
- goto ign;
- if(na <= n_count) {
- na += NINC;
- n_list = realloc(n_list, na*sizeof(File));
- }
- n_list[n_count].name = strdup(d[i].name);
- n_list[n_count].time = d[i].mtime;
- n_list[n_count].length = d[i].length;
- n_count++;
- ign:;
- }
- free(d);
- close(fd);
- qsort(n_list, n_count, sizeof(File), fcmp);
- }
- void
- print_item(char *file)
- {
- char name[4096], *p, *ep;
- Dir *dbuf;
- int f, c;
- int bol, bop;
- sprint(name, "%s/%s", NEWS, file);
- f = open(name, OREAD);
- if(f < 0) {
- fprint(2, "news: ");
- perror(name);
- return;
- }
- strcpy(name, "...");
- dbuf = dirfstat(f);
- if(dbuf == nil)
- return;
- Bprint(&bout, "\n%s (%s) %s\n", file,
- dbuf->muid[0]? dbuf->muid : dbuf->uid,
- asctime(localtime(dbuf->mtime)));
- free(dbuf);
- bol = 1; /* beginning of line ...\n */
- bop = 1; /* beginning of page ...\n\n */
- for(;;) {
- c = read(f, name, sizeof(name));
- if(c <= 0)
- break;
- p = name;
- ep = p+c;
- while(p < ep) {
- c = *p++;
- if(c == '\n') {
- if(!bop) {
- Bputc(&bout, c);
- if(bol)
- bop = 1;
- bol = 1;
- }
- continue;
- }
- if(bol) {
- Bputc(&bout, '\t');
- bol = 0;
- bop = 0;
- }
- Bputc(&bout, c);
- }
- }
- if(!bol)
- Bputc(&bout, '\n');
- close(f);
- }
- void
- eachitem(void (*emit)(char*), int all, int update)
- {
- int i;
- read_dir(update);
- for(i=0; i<n_count; i++) {
- if(n_list[i].name[0] == 0) { /* newstime */
- if(all)
- continue;
- break;
- }
- if(n_list[i].length == 0) /* in progress */
- continue;
- (*emit)(n_list[i].name);
- }
- }
- void
- note(char *file)
- {
- if(!n_items)
- Bprint(&bout, "news:");
- Bprint(&bout, " %s", file);
- n_items++;
- }
|