/* * 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}; typedefstruct{ long time; char *name; vlong length;} File;File* n_list;int n_count;int n_items;Biobuf bout; int fcmp(void *a, 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); voidmain(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);} intfcmp(void *a, 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. */voidread_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);} voidprint_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);} voideachitem(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); }} voidnote(char *file){ if(!n_items) Bprint(&bout, "news:"); Bprint(&bout, " %s", file); n_items++;}
/*
* 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
{
long time;
char *name;
vlong length;
} File;
File* n_list;
int n_count;
int n_items;
Biobuf bout;
int fcmp(void *a, 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(void *a, 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++;
}