Blame


1 17e5fb89 2004-04-21 devnull /*
2 17e5fb89 2004-04-21 devnull * news foo prints /lib/news/foo
3 17e5fb89 2004-04-21 devnull * news -a prints all news items, latest first
4 17e5fb89 2004-04-21 devnull * news -n lists names of new items
5 17e5fb89 2004-04-21 devnull * news prints items changed since last news
6 17e5fb89 2004-04-21 devnull */
7 17e5fb89 2004-04-21 devnull
8 17e5fb89 2004-04-21 devnull #include <u.h>
9 17e5fb89 2004-04-21 devnull #include <libc.h>
10 17e5fb89 2004-04-21 devnull #include <bio.h>
11 17e5fb89 2004-04-21 devnull
12 17e5fb89 2004-04-21 devnull #define NINC 50 /* Multiples of directory allocation */
13 17e5fb89 2004-04-21 devnull char *NEWS = "#9/news";
14 17e5fb89 2004-04-21 devnull char TFILE[] = "%s/lib/newstime";
15 17e5fb89 2004-04-21 devnull
16 17e5fb89 2004-04-21 devnull /*
17 17e5fb89 2004-04-21 devnull * The following items should not be printed.
18 17e5fb89 2004-04-21 devnull */
19 17e5fb89 2004-04-21 devnull char* ignore[] =
20 17e5fb89 2004-04-21 devnull {
21 17e5fb89 2004-04-21 devnull "core",
22 17e5fb89 2004-04-21 devnull "dead.letter",
23 17e5fb89 2004-04-21 devnull 0
24 17e5fb89 2004-04-21 devnull };
25 17e5fb89 2004-04-21 devnull
26 17e5fb89 2004-04-21 devnull typedef
27 17e5fb89 2004-04-21 devnull struct
28 17e5fb89 2004-04-21 devnull {
29 17e5fb89 2004-04-21 devnull long time;
30 17e5fb89 2004-04-21 devnull char *name;
31 17e5fb89 2004-04-21 devnull vlong length;
32 17e5fb89 2004-04-21 devnull } File;
33 17e5fb89 2004-04-21 devnull File* n_list;
34 17e5fb89 2004-04-21 devnull int n_count;
35 17e5fb89 2004-04-21 devnull int n_items;
36 17e5fb89 2004-04-21 devnull Biobuf bout;
37 17e5fb89 2004-04-21 devnull
38 17e5fb89 2004-04-21 devnull int fcmp(const void *a, const void *b);
39 17e5fb89 2004-04-21 devnull void read_dir(int update);
40 17e5fb89 2004-04-21 devnull void print_item(char *f);
41 17e5fb89 2004-04-21 devnull void eachitem(void (*emit)(char*), int all, int update);
42 17e5fb89 2004-04-21 devnull void note(char *s);
43 17e5fb89 2004-04-21 devnull
44 17e5fb89 2004-04-21 devnull void
45 17e5fb89 2004-04-21 devnull main(int argc, char *argv[])
46 17e5fb89 2004-04-21 devnull {
47 17e5fb89 2004-04-21 devnull int i;
48 17e5fb89 2004-04-21 devnull
49 17e5fb89 2004-04-21 devnull NEWS = unsharp(NEWS);
50 17e5fb89 2004-04-21 devnull
51 17e5fb89 2004-04-21 devnull Binit(&bout, 1, OWRITE);
52 17e5fb89 2004-04-21 devnull if(argc == 1) {
53 17e5fb89 2004-04-21 devnull eachitem(print_item, 0, 1);
54 17e5fb89 2004-04-21 devnull exits(0);
55 17e5fb89 2004-04-21 devnull }
56 17e5fb89 2004-04-21 devnull ARGBEGIN{
57 17e5fb89 2004-04-21 devnull case 'a': /* print all */
58 17e5fb89 2004-04-21 devnull eachitem(print_item, 1, 0);
59 17e5fb89 2004-04-21 devnull break;
60 17e5fb89 2004-04-21 devnull
61 17e5fb89 2004-04-21 devnull case 'n': /* names only */
62 17e5fb89 2004-04-21 devnull eachitem(note, 0, 0);
63 17e5fb89 2004-04-21 devnull if(n_items)
64 17e5fb89 2004-04-21 devnull Bputc(&bout, '\n');
65 17e5fb89 2004-04-21 devnull break;
66 17e5fb89 2004-04-21 devnull
67 17e5fb89 2004-04-21 devnull default:
68 17e5fb89 2004-04-21 devnull fprint(2, "news: bad option %c\n", ARGC());
69 17e5fb89 2004-04-21 devnull exits("usage");
70 17e5fb89 2004-04-21 devnull }ARGEND
71 17e5fb89 2004-04-21 devnull for(i=0; i<argc; i++)
72 17e5fb89 2004-04-21 devnull print_item(argv[i]);
73 17e5fb89 2004-04-21 devnull exits(0);
74 17e5fb89 2004-04-21 devnull }
75 17e5fb89 2004-04-21 devnull
76 17e5fb89 2004-04-21 devnull int
77 17e5fb89 2004-04-21 devnull fcmp(const void *a, const void *b)
78 17e5fb89 2004-04-21 devnull {
79 17e5fb89 2004-04-21 devnull long x;
80 17e5fb89 2004-04-21 devnull
81 17e5fb89 2004-04-21 devnull x = ((File*)b)->time - ((File*)a)->time;
82 17e5fb89 2004-04-21 devnull if(x < 0)
83 17e5fb89 2004-04-21 devnull return -1;
84 17e5fb89 2004-04-21 devnull if(x > 0)
85 17e5fb89 2004-04-21 devnull return 1;
86 17e5fb89 2004-04-21 devnull return 0;
87 17e5fb89 2004-04-21 devnull }
88 17e5fb89 2004-04-21 devnull
89 17e5fb89 2004-04-21 devnull /*
90 17e5fb89 2004-04-21 devnull * read_dir: get the file names and modification dates for the
91 17e5fb89 2004-04-21 devnull * files in /usr/news into n_list; sort them in reverse by
92 17e5fb89 2004-04-21 devnull * modification date.
93 17e5fb89 2004-04-21 devnull */
94 17e5fb89 2004-04-21 devnull void
95 17e5fb89 2004-04-21 devnull read_dir(int update)
96 17e5fb89 2004-04-21 devnull {
97 17e5fb89 2004-04-21 devnull Dir *d;
98 17e5fb89 2004-04-21 devnull char newstime[100], *home;
99 17e5fb89 2004-04-21 devnull int i, j, n, na, fd;
100 17e5fb89 2004-04-21 devnull
101 17e5fb89 2004-04-21 devnull n_count = 0;
102 17e5fb89 2004-04-21 devnull n_list = malloc(NINC*sizeof(File));
103 17e5fb89 2004-04-21 devnull na = NINC;
104 c8b6342d 2005-01-13 devnull home = getenv("HOME");
105 17e5fb89 2004-04-21 devnull if(home) {
106 17e5fb89 2004-04-21 devnull sprint(newstime, TFILE, home);
107 17e5fb89 2004-04-21 devnull d = dirstat(newstime);
108 17e5fb89 2004-04-21 devnull if(d != nil) {
109 17e5fb89 2004-04-21 devnull n_list[n_count].name = strdup("");
110 17e5fb89 2004-04-21 devnull n_list[n_count].time =d->mtime-1;
111 17e5fb89 2004-04-21 devnull n_list[n_count].length = 0;
112 17e5fb89 2004-04-21 devnull n_count++;
113 17e5fb89 2004-04-21 devnull free(d);
114 17e5fb89 2004-04-21 devnull }
115 17e5fb89 2004-04-21 devnull if(update) {
116 17e5fb89 2004-04-21 devnull fd = create(newstime, OWRITE, 0644);
117 17e5fb89 2004-04-21 devnull if(fd >= 0)
118 17e5fb89 2004-04-21 devnull close(fd);
119 17e5fb89 2004-04-21 devnull }
120 17e5fb89 2004-04-21 devnull }
121 17e5fb89 2004-04-21 devnull fd = open(NEWS, OREAD);
122 17e5fb89 2004-04-21 devnull if(fd < 0) {
123 17e5fb89 2004-04-21 devnull fprint(2, "news: ");
124 17e5fb89 2004-04-21 devnull perror(NEWS);
125 17e5fb89 2004-04-21 devnull exits(NEWS);
126 17e5fb89 2004-04-21 devnull }
127 17e5fb89 2004-04-21 devnull
128 17e5fb89 2004-04-21 devnull n = dirreadall(fd, &d);
129 17e5fb89 2004-04-21 devnull for(i=0; i<n; i++) {
130 17e5fb89 2004-04-21 devnull for(j=0; ignore[j]; j++)
131 17e5fb89 2004-04-21 devnull if(strcmp(ignore[j], d[i].name) == 0)
132 17e5fb89 2004-04-21 devnull goto ign;
133 17e5fb89 2004-04-21 devnull if(na <= n_count) {
134 17e5fb89 2004-04-21 devnull na += NINC;
135 17e5fb89 2004-04-21 devnull n_list = realloc(n_list, na*sizeof(File));
136 17e5fb89 2004-04-21 devnull }
137 17e5fb89 2004-04-21 devnull n_list[n_count].name = strdup(d[i].name);
138 17e5fb89 2004-04-21 devnull n_list[n_count].time = d[i].mtime;
139 17e5fb89 2004-04-21 devnull n_list[n_count].length = d[i].length;
140 17e5fb89 2004-04-21 devnull n_count++;
141 17e5fb89 2004-04-21 devnull ign:;
142 17e5fb89 2004-04-21 devnull }
143 17e5fb89 2004-04-21 devnull free(d);
144 17e5fb89 2004-04-21 devnull
145 17e5fb89 2004-04-21 devnull close(fd);
146 17e5fb89 2004-04-21 devnull qsort(n_list, n_count, sizeof(File), fcmp);
147 17e5fb89 2004-04-21 devnull }
148 17e5fb89 2004-04-21 devnull
149 17e5fb89 2004-04-21 devnull void
150 17e5fb89 2004-04-21 devnull print_item(char *file)
151 17e5fb89 2004-04-21 devnull {
152 17e5fb89 2004-04-21 devnull char name[4096], *p, *ep;
153 17e5fb89 2004-04-21 devnull Dir *dbuf;
154 17e5fb89 2004-04-21 devnull int f, c;
155 17e5fb89 2004-04-21 devnull int bol, bop;
156 17e5fb89 2004-04-21 devnull
157 17e5fb89 2004-04-21 devnull sprint(name, "%s/%s", NEWS, file);
158 17e5fb89 2004-04-21 devnull f = open(name, OREAD);
159 17e5fb89 2004-04-21 devnull if(f < 0) {
160 17e5fb89 2004-04-21 devnull fprint(2, "news: ");
161 17e5fb89 2004-04-21 devnull perror(name);
162 17e5fb89 2004-04-21 devnull return;
163 17e5fb89 2004-04-21 devnull }
164 17e5fb89 2004-04-21 devnull strcpy(name, "...");
165 17e5fb89 2004-04-21 devnull dbuf = dirfstat(f);
166 17e5fb89 2004-04-21 devnull if(dbuf == nil)
167 17e5fb89 2004-04-21 devnull return;
168 17e5fb89 2004-04-21 devnull Bprint(&bout, "\n%s (%s) %s\n", file,
169 17e5fb89 2004-04-21 devnull dbuf->muid[0]? dbuf->muid : dbuf->uid,
170 17e5fb89 2004-04-21 devnull asctime(localtime(dbuf->mtime)));
171 17e5fb89 2004-04-21 devnull free(dbuf);
172 17e5fb89 2004-04-21 devnull
173 17e5fb89 2004-04-21 devnull bol = 1; /* beginning of line ...\n */
174 17e5fb89 2004-04-21 devnull bop = 1; /* beginning of page ...\n\n */
175 17e5fb89 2004-04-21 devnull for(;;) {
176 17e5fb89 2004-04-21 devnull c = read(f, name, sizeof(name));
177 17e5fb89 2004-04-21 devnull if(c <= 0)
178 17e5fb89 2004-04-21 devnull break;
179 17e5fb89 2004-04-21 devnull p = name;
180 17e5fb89 2004-04-21 devnull ep = p+c;
181 17e5fb89 2004-04-21 devnull while(p < ep) {
182 17e5fb89 2004-04-21 devnull c = *p++;
183 17e5fb89 2004-04-21 devnull if(c == '\n') {
184 17e5fb89 2004-04-21 devnull if(!bop) {
185 17e5fb89 2004-04-21 devnull Bputc(&bout, c);
186 17e5fb89 2004-04-21 devnull if(bol)
187 17e5fb89 2004-04-21 devnull bop = 1;
188 17e5fb89 2004-04-21 devnull bol = 1;
189 17e5fb89 2004-04-21 devnull }
190 17e5fb89 2004-04-21 devnull continue;
191 17e5fb89 2004-04-21 devnull }
192 17e5fb89 2004-04-21 devnull if(bol) {
193 17e5fb89 2004-04-21 devnull Bputc(&bout, '\t');
194 17e5fb89 2004-04-21 devnull bol = 0;
195 17e5fb89 2004-04-21 devnull bop = 0;
196 17e5fb89 2004-04-21 devnull }
197 17e5fb89 2004-04-21 devnull Bputc(&bout, c);
198 17e5fb89 2004-04-21 devnull }
199 17e5fb89 2004-04-21 devnull }
200 17e5fb89 2004-04-21 devnull if(!bol)
201 17e5fb89 2004-04-21 devnull Bputc(&bout, '\n');
202 17e5fb89 2004-04-21 devnull close(f);
203 17e5fb89 2004-04-21 devnull }
204 17e5fb89 2004-04-21 devnull
205 17e5fb89 2004-04-21 devnull void
206 17e5fb89 2004-04-21 devnull eachitem(void (*emit)(char*), int all, int update)
207 17e5fb89 2004-04-21 devnull {
208 17e5fb89 2004-04-21 devnull int i;
209 17e5fb89 2004-04-21 devnull
210 17e5fb89 2004-04-21 devnull read_dir(update);
211 17e5fb89 2004-04-21 devnull for(i=0; i<n_count; i++) {
212 17e5fb89 2004-04-21 devnull if(n_list[i].name[0] == 0) { /* newstime */
213 17e5fb89 2004-04-21 devnull if(all)
214 17e5fb89 2004-04-21 devnull continue;
215 17e5fb89 2004-04-21 devnull break;
216 17e5fb89 2004-04-21 devnull }
217 17e5fb89 2004-04-21 devnull if(n_list[i].length == 0) /* in progress */
218 17e5fb89 2004-04-21 devnull continue;
219 17e5fb89 2004-04-21 devnull (*emit)(n_list[i].name);
220 17e5fb89 2004-04-21 devnull }
221 17e5fb89 2004-04-21 devnull }
222 17e5fb89 2004-04-21 devnull
223 17e5fb89 2004-04-21 devnull void
224 17e5fb89 2004-04-21 devnull note(char *file)
225 17e5fb89 2004-04-21 devnull {
226 17e5fb89 2004-04-21 devnull
227 17e5fb89 2004-04-21 devnull if(!n_items)
228 17e5fb89 2004-04-21 devnull Bprint(&bout, "news:");
229 17e5fb89 2004-04-21 devnull Bprint(&bout, " %s", file);
230 17e5fb89 2004-04-21 devnull n_items++;
231 17e5fb89 2004-04-21 devnull }