|
|
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 <ndir.h>
15: #include <pwd.h>
16:
17: /*
18: * The following items should not be printed.
19: */
20: char *ignore[] = {
21: "core",
22: "dead.letter",
23: NULL
24: };
25:
26: struct n_file {
27: long n_time;
28: char n_name[MAXNAMLEN];
29: } *n_list;
30:
31: char NEWS[] = "/usr/news";
32:
33: int n_count;
34: char stdbuf[BUFSIZ];
35:
36: jmp_buf save_addr;
37:
38: main (argc, argv)
39: int argc;
40: char **argv;
41: {
42: int print_item(), notify(), count();
43:
44: setbuf (stdout, stdbuf);
45: initialize();
46: read_dir();
47: if (argc <= 1)
48: late_news (print_item, 1);
49: else if ( argc == 2 && argv[1][0] == '-'
50: && argv[1][1] != '\0' && argv[1][2] == '\0')
51: switch (argv[1][1]) {
52: case 'a':
53: all_news();
54: break;
55:
56: case 'n':
57: late_news (notify, 0);
58: break;
59:
60: case 's':
61: late_news (count, 0);
62: break;
63:
64: default:
65: fprintf (stderr, "news: bad option %s\n", argv[1]);
66: exit (1);
67: }
68: else {
69: int i;
70: for (i=1; i<argc; i++)
71: print_item (argv[i]);
72: }
73: return 0;
74: }
75:
76: /*
77: * read_dir: get the file names and modification dates for the
78: * files in /usr/news into n_list; sort them in reverse by
79: * modification date. We assume /usr/news is the working directory.
80: */
81:
82: read_dir()
83: {
84: struct direct *nf;
85: struct stat sbuf;
86: char fname[MAXNAMLEN];
87: DIR *dirp;
88: int i, j;
89: char *malloc(), *realloc();
90:
91: /* Open the current directory */
92: if ((dirp = opendir(".")) == NULL) {
93: fprintf (stderr, "news: ");
94: perror (NEWS);
95: exit (1);
96: }
97:
98: /* Read the file names into n_list */
99: n_count = 0;
100: while (nf = readdir(dirp)) {
101: strncpy (fname, nf->d_name, (unsigned) strlen(nf->d_name) + 1);
102: if (nf->d_ino != 0 && stat (fname, &sbuf) >= 0
103: && (sbuf.st_mode & S_IFMT) == S_IFREG) {
104: register char **p;
105: p = ignore;
106: while (*p && strncmp (*p, nf->d_name, MAXNAMLEN))
107: ++p;
108: if (!*p) {
109: if (n_count++ > 0)
110: n_list = (struct n_file *)
111: realloc ((char *) n_list,
112: (unsigned)
113: (sizeof (struct n_file)
114: * n_count));
115: else
116: n_list = (struct n_file *) malloc
117: ((unsigned)
118: (sizeof (struct n_file) *
119: n_count));
120: if (n_list == NULL) {
121: fprintf (stderr, "news: no storage\n");
122: exit (1);
123: }
124: n_list[n_count-1].n_time = sbuf.st_mtime;
125: strncpy (n_list[n_count-1].n_name,
126: nf->d_name, MAXNAMLEN);
127: }
128: }
129: }
130:
131: /* Sort the elements of n_list in decreasing time order */
132: for (i=1; i<n_count; i++)
133: for (j=0; j<i; j++)
134: if (n_list[j].n_time < n_list[i].n_time) {
135: struct n_file temp;
136: temp = n_list[i];
137: n_list[i] = n_list[j];
138: n_list[j] = temp;
139: }
140:
141: /* Clean up */
142: closedir(dirp);
143: }
144:
145: initialize()
146: {
147: extern _exit();
148: if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
149: signal (SIGQUIT, _exit);
150: umask (022);
151: if (chdir (NEWS) < 0) {
152: fprintf (stderr, "news: ");
153: perror (NEWS);
154: exit (1);
155: }
156: }
157:
158: all_news()
159: {
160: int i;
161:
162: for (i=0; i<n_count; i++)
163: print_item (n_list[i].n_name);
164: }
165:
166: print_item (f)
167: char *f;
168: {
169: FILE *fd;
170: char fname[MAXNAMLEN+1];
171: static int firstitem = 1;
172: int onintr();
173: struct passwd *getpwuid();
174:
175: if (f == NULL) {
176: return;
177: }
178: strncpy (fname, f, MAXNAMLEN);
179: fname[MAXNAMLEN] = '\0';
180: if ((fd = fopen (fname, "r")) == NULL) {
181: fprintf (stderr, "news: %s/", NEWS);
182: perror (fname);
183: } else {
184: register int c, ip, op;
185: struct stat sbuf;
186: char *ctime();
187: struct passwd *pw;
188:
189: fstat (fileno (fd), &sbuf);
190: if (firstitem) {
191: firstitem = 0;
192: putchar ('\n');
193: }
194: if (setjmp(save_addr))
195: goto finish;
196: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
197: signal(SIGINT, onintr);
198: printf ("%s ", fname);
199: pw = getpwuid (sbuf.st_uid);
200: if (pw)
201: printf ("(%s)", pw->pw_name);
202: else
203: printf (".....");
204: printf (" %s\n", ctime (&sbuf.st_mtime));
205:
206: /*
207: * copy the news item to the standard output
208: *
209: * ip is the output character position corresponding
210: * to the present input character. op is the
211: * actual current output character position.
212: */
213: while ((c = getc (fd)) != EOF)
214: putchar (c);
215: fflush (stdout);
216: finish:
217: putchar ('\n');
218: fclose (fd);
219: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
220: signal(SIGINT, SIG_DFL);
221: }
222: }
223:
224: late_news (emit, update)
225: int (*emit)(), update;
226: {
227: long cutoff;
228: int i;
229: char fname[50], *getenv(), *cp;
230: struct stat newstime;
231: int fd;
232: struct {
233: long actime, modtime;
234: } utb;
235:
236: /* Determine the time when last called */
237: cp = getenv ("HOME");
238: if (cp == NULL) {
239: fprintf (stderr, "news: cannot find HOME variable\n");
240: exit (1);
241: }
242: strcpy (fname, cp);
243: strcat (fname, "/");
244: strcat (fname, ".news_time");
245: cutoff = stat (fname, &newstime) < 0? 0: newstime.st_mtime;
246:
247: /* Print the recent items */
248: for (i=0; i<n_count && n_list[i].n_time > cutoff; i++)
249: (*emit) (n_list[i].n_name);
250: (*emit) ((char *) NULL);
251: fflush (stdout);
252:
253: if (update) {
254: /* Re-create the file and refresh the update time */
255: if (n_count > 0 && (fd = creat (fname, 0666)) >= 0) {
256: utb.actime = utb.modtime = n_list[0].n_time;
257: close (fd);
258: utime (fname, &utb);
259: }
260: }
261: }
262:
263: notify (s)
264: char *s;
265: {
266: static int first = 1;
267:
268: if (s) {
269: if (first) {
270: first = 0;
271: printf ("news:", NEWS);
272: }
273: printf (" %.14s", s);
274: } else if (!first)
275: putchar ('\n');
276: }
277:
278: /*ARGSUSED*/
279: count (s)
280: char *s;
281: {
282: static int nitems = 0;
283:
284: if (s)
285: nitems++;
286: else if (nitems) {
287: printf ("%d news item", nitems);
288: if (nitems > 1)
289: putchar ('s');
290: printf (".\n");
291: }
292:
293: }
294:
295: onintr()
296: {
297: sleep(2);
298: longjmp(save_addr, 1);
299: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.