diff options
author | rsc <devnull@localhost> | 2004-04-21 23:22:06 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-04-21 23:22:06 +0000 |
commit | 17e5fb8973d9e48ef53a88eb78f845f8a7b41a5b (patch) | |
tree | 921c649de0d83bdde4561f5868e5ff3ab9986af8 /src/cmd/news.c | |
parent | 3e63e5c271f7a7013dc4b3fedfb83c2d547b8c26 (diff) | |
download | plan9port-17e5fb8973d9e48ef53a88eb78f845f8a7b41a5b.tar.gz plan9port-17e5fb8973d9e48ef53a88eb78f845f8a7b41a5b.tar.bz2 plan9port-17e5fb8973d9e48ef53a88eb78f845f8a7b41a5b.zip |
add new guys
Diffstat (limited to 'src/cmd/news.c')
-rw-r--r-- | src/cmd/news.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/src/cmd/news.c b/src/cmd/news.c new file mode 100644 index 00000000..c6a99a30 --- /dev/null +++ b/src/cmd/news.c @@ -0,0 +1,231 @@ +/* + * 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 = "#9/news"; +char TFILE[] = "%s/lib/newstime"; + +/* + * The following items should not be printed. + */ +char* ignore[] = +{ + "core", + "dead.letter", + 0 +}; + +typedef +struct +{ + long time; + char *name; + vlong 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; + + NEWS = unsharp(NEWS); + + 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) +{ + long 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++; +} |