xref: /onnv-gate/usr/src/cmd/news/news.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.15	*/
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate /*
29*0Sstevel@tonic-gate 	news foo	prints /var/news/foo
30*0Sstevel@tonic-gate 	news -a		prints all news items, latest first
31*0Sstevel@tonic-gate 	news -n		lists names of new items
32*0Sstevel@tonic-gate 	news -s		tells count of new items only
33*0Sstevel@tonic-gate 	news		prints items changed since last news
34*0Sstevel@tonic-gate */
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include <stdio.h>
37*0Sstevel@tonic-gate #include <sys/types.h>
38*0Sstevel@tonic-gate #include <stdlib.h>
39*0Sstevel@tonic-gate #include <unistd.h>
40*0Sstevel@tonic-gate #include <sys/stat.h>
41*0Sstevel@tonic-gate #include <setjmp.h>
42*0Sstevel@tonic-gate #include <signal.h>
43*0Sstevel@tonic-gate #include <dirent.h>
44*0Sstevel@tonic-gate #include <pwd.h>
45*0Sstevel@tonic-gate #include <time.h>
46*0Sstevel@tonic-gate #include <locale.h>
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate #define INDENT 3
49*0Sstevel@tonic-gate #define	RD_WR_ALL	(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate #define	DATE_FMT	"%a %b %e %H:%M:%S %Y"
52*0Sstevel@tonic-gate /*
53*0Sstevel@tonic-gate  *	%a	abbreviated weekday name
54*0Sstevel@tonic-gate  *	%b	abbreviated month name
55*0Sstevel@tonic-gate  *	%e	day of month
56*0Sstevel@tonic-gate  *	%H	hour (24-hour clock)
57*0Sstevel@tonic-gate  *	%M	minute
58*0Sstevel@tonic-gate  *	%S	second
59*0Sstevel@tonic-gate  *	%Y	year
60*0Sstevel@tonic-gate  */
61*0Sstevel@tonic-gate /*
62*0Sstevel@tonic-gate 	The following items should not be printed.
63*0Sstevel@tonic-gate */
64*0Sstevel@tonic-gate char	*ignore[] = {
65*0Sstevel@tonic-gate 		"core",
66*0Sstevel@tonic-gate 		NULL
67*0Sstevel@tonic-gate };
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate struct n_file {
70*0Sstevel@tonic-gate 	long n_time;
71*0Sstevel@tonic-gate 	char n_name[MAXNAMLEN];
72*0Sstevel@tonic-gate } *n_list;
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate char	NEWS[] = "/var/news";	/* directory for news items */
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate int	aopt = 0;	/* 1 say -a specified */
77*0Sstevel@tonic-gate int	n_count;	/* number of items in NEWS directory */
78*0Sstevel@tonic-gate int	number_read;	/* number of items read */
79*0Sstevel@tonic-gate int	nopt = 0;	/* 1 say -n specified */
80*0Sstevel@tonic-gate int	optsw;		/* for getopt */
81*0Sstevel@tonic-gate int	opt = 0;	/* number of options specified */
82*0Sstevel@tonic-gate int	sopt = 0;	/* 1 says -s specified */
83*0Sstevel@tonic-gate char	stdbuf[BUFSIZ];
84*0Sstevel@tonic-gate char	time_buf[50];	/* holds date and time string */
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate jmp_buf	save_addr;
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate main (argc, argv)
89*0Sstevel@tonic-gate int	argc;
90*0Sstevel@tonic-gate char	**argv;
91*0Sstevel@tonic-gate {
92*0Sstevel@tonic-gate 	int print_item(), notify(), count(),i;
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	(void)setlocale(LC_ALL, "");
95*0Sstevel@tonic-gate 	setbuf (stdout, stdbuf);
96*0Sstevel@tonic-gate 	initialize();
97*0Sstevel@tonic-gate 	read_dir();
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	if (argc <= 1) {
100*0Sstevel@tonic-gate 		late_news (print_item, 1);
101*0Sstevel@tonic-gate 		ck_num();
102*0Sstevel@tonic-gate 	}
103*0Sstevel@tonic-gate 	else while ((optsw = getopt(argc, argv, "ans")) != EOF)
104*0Sstevel@tonic-gate 		switch(optsw) {
105*0Sstevel@tonic-gate 		case 'a':
106*0Sstevel@tonic-gate 			aopt++;
107*0Sstevel@tonic-gate 			opt++;
108*0Sstevel@tonic-gate 			break;
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 		case 'n':
111*0Sstevel@tonic-gate 			nopt++;
112*0Sstevel@tonic-gate 			opt++;
113*0Sstevel@tonic-gate 			break;
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 		case 's':
116*0Sstevel@tonic-gate 			sopt++;
117*0Sstevel@tonic-gate 			opt++;
118*0Sstevel@tonic-gate 			break;
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 		default:
121*0Sstevel@tonic-gate 			fprintf (stderr, "usage: news [-a] [-n] [-s] [items]\n");
122*0Sstevel@tonic-gate 			exit (1);
123*0Sstevel@tonic-gate 	}
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate         if (opt > 1) {
126*0Sstevel@tonic-gate         	fprintf(stderr, "news: options are mutually exclusive\n");
127*0Sstevel@tonic-gate         	exit(1);
128*0Sstevel@tonic-gate 	}
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate         if (opt > 0 && argc > 2) {
131*0Sstevel@tonic-gate         	fprintf(stderr, "news: options are not allowed with file names\n");
132*0Sstevel@tonic-gate         	exit(1);
133*0Sstevel@tonic-gate 	}
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 	if (aopt) {
136*0Sstevel@tonic-gate 		all_news();
137*0Sstevel@tonic-gate 		ck_num();
138*0Sstevel@tonic-gate 		exit(0);
139*0Sstevel@tonic-gate 	}
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate 	if (nopt) {
142*0Sstevel@tonic-gate 		late_news (notify, 0);
143*0Sstevel@tonic-gate 		ck_num();
144*0Sstevel@tonic-gate 		exit(0);
145*0Sstevel@tonic-gate 	}
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 	if (sopt) {
148*0Sstevel@tonic-gate 		late_news (count, 0);
149*0Sstevel@tonic-gate 		exit(0);
150*0Sstevel@tonic-gate 	}
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 	for (i=1; i<argc; i++) print_item (argv[i]);
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate 	exit(0);
155*0Sstevel@tonic-gate }
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate /*
158*0Sstevel@tonic-gate  *	read_dir: get the file names and modification dates for the
159*0Sstevel@tonic-gate  *	files in /var/news into n_list; sort them in reverse by
160*0Sstevel@tonic-gate  *	modification date. We assume /var/news is the working directory.
161*0Sstevel@tonic-gate  */
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate read_dir()
164*0Sstevel@tonic-gate {
165*0Sstevel@tonic-gate 	struct dirent *nf, *readdir();
166*0Sstevel@tonic-gate 	struct stat sbuf;
167*0Sstevel@tonic-gate 	char fname[MAXNAMLEN];
168*0Sstevel@tonic-gate 	DIR *dirp;
169*0Sstevel@tonic-gate 	int i, j;
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate 	/* Open the current directory */
172*0Sstevel@tonic-gate 	if ((dirp = opendir(".")) == NULL) {
173*0Sstevel@tonic-gate 		fprintf (stderr, "Cannot open %s\n", NEWS);
174*0Sstevel@tonic-gate 		exit (1);
175*0Sstevel@tonic-gate 	}
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 	/* Read the file names into n_list */
178*0Sstevel@tonic-gate 	n_count = 0;
179*0Sstevel@tonic-gate 	while (nf = readdir(dirp)) {
180*0Sstevel@tonic-gate 		strncpy (fname, nf->d_name, (unsigned) strlen(nf->d_name) + 1);
181*0Sstevel@tonic-gate 		if (nf->d_ino != (ino_t)0 && stat (fname, &sbuf) >= 0
182*0Sstevel@tonic-gate 		 && (sbuf.st_mode & S_IFMT) == S_IFREG) {
183*0Sstevel@tonic-gate 			register char **p;
184*0Sstevel@tonic-gate 			p = ignore;
185*0Sstevel@tonic-gate 			while (*p && strncmp (*p, nf->d_name, MAXNAMLEN))
186*0Sstevel@tonic-gate 				++p;
187*0Sstevel@tonic-gate 			if (!*p) {
188*0Sstevel@tonic-gate 				if (n_count++ > 0)
189*0Sstevel@tonic-gate 					n_list = (struct n_file *)
190*0Sstevel@tonic-gate 						realloc ((char *) n_list,
191*0Sstevel@tonic-gate 						(unsigned)
192*0Sstevel@tonic-gate 						(sizeof (struct n_file)
193*0Sstevel@tonic-gate 						    * n_count));
194*0Sstevel@tonic-gate 				else
195*0Sstevel@tonic-gate 					n_list = (struct n_file *) malloc
196*0Sstevel@tonic-gate 						((unsigned)
197*0Sstevel@tonic-gate 						(sizeof (struct n_file) *
198*0Sstevel@tonic-gate 						n_count));
199*0Sstevel@tonic-gate 				if (n_list == NULL) {
200*0Sstevel@tonic-gate 					fprintf (stderr, "No storage\n");
201*0Sstevel@tonic-gate 					exit (1);
202*0Sstevel@tonic-gate 				}
203*0Sstevel@tonic-gate 				n_list[n_count-1].n_time = sbuf.st_mtime;
204*0Sstevel@tonic-gate 				strncpy (n_list[n_count-1].n_name,
205*0Sstevel@tonic-gate 					nf->d_name, MAXNAMLEN);
206*0Sstevel@tonic-gate 			}
207*0Sstevel@tonic-gate 		}
208*0Sstevel@tonic-gate 	}
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 	/* Sort the elements of n_list in decreasing time order */
211*0Sstevel@tonic-gate 	for (i=1; i<n_count; i++)
212*0Sstevel@tonic-gate 		for (j=0; j<i; j++)
213*0Sstevel@tonic-gate 			if (n_list[j].n_time < n_list[i].n_time) {
214*0Sstevel@tonic-gate 				struct n_file temp;
215*0Sstevel@tonic-gate 				temp = n_list[i];
216*0Sstevel@tonic-gate 				n_list[i] = n_list[j];
217*0Sstevel@tonic-gate 				n_list[j] = temp;
218*0Sstevel@tonic-gate 			}
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	/* Clean up */
221*0Sstevel@tonic-gate 	closedir(dirp);
222*0Sstevel@tonic-gate }
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate initialize()
225*0Sstevel@tonic-gate {
226*0Sstevel@tonic-gate 	if (signal (SIGQUIT, SIG_IGN) != (void(*)())SIG_IGN)
227*0Sstevel@tonic-gate 		signal (SIGQUIT, _exit);
228*0Sstevel@tonic-gate 	umask (((~(S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) & S_IAMB));
229*0Sstevel@tonic-gate 	if (chdir (NEWS) < 0) {
230*0Sstevel@tonic-gate 		fprintf (stderr, "Cannot chdir to %s\n", NEWS);
231*0Sstevel@tonic-gate 		exit (1);
232*0Sstevel@tonic-gate 	}
233*0Sstevel@tonic-gate }
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate all_news()
236*0Sstevel@tonic-gate {
237*0Sstevel@tonic-gate 	int i;
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	for (i=0; i<n_count; i++)
240*0Sstevel@tonic-gate 		print_item (n_list[i].n_name);
241*0Sstevel@tonic-gate }
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate print_item (f)
244*0Sstevel@tonic-gate 	char *f;
245*0Sstevel@tonic-gate {
246*0Sstevel@tonic-gate 	FILE *fd;
247*0Sstevel@tonic-gate 	char fname[MAXNAMLEN+1];
248*0Sstevel@tonic-gate 	static int firstitem = 1;
249*0Sstevel@tonic-gate 	void onintr();
250*0Sstevel@tonic-gate 	struct passwd *getpwuid();
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate 	if (f == NULL) {
253*0Sstevel@tonic-gate 		return;
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate 	strncpy (fname, f, MAXNAMLEN);
256*0Sstevel@tonic-gate 	fname[MAXNAMLEN] = '\0';
257*0Sstevel@tonic-gate 	if ((fd = fopen (fname, "r")) == NULL)
258*0Sstevel@tonic-gate 		printf ("Cannot open %s/%s\n", NEWS, fname);
259*0Sstevel@tonic-gate 	else {
260*0Sstevel@tonic-gate 		register int c, ip, op;
261*0Sstevel@tonic-gate 		struct stat sbuf;
262*0Sstevel@tonic-gate 		struct passwd *pw;
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate 		fstat (fileno (fd), &sbuf);
265*0Sstevel@tonic-gate 		if (firstitem) {
266*0Sstevel@tonic-gate 			firstitem = 0;
267*0Sstevel@tonic-gate 			putchar ('\n');
268*0Sstevel@tonic-gate 		}
269*0Sstevel@tonic-gate 		if (setjmp(save_addr))
270*0Sstevel@tonic-gate 			goto finish;
271*0Sstevel@tonic-gate 		if (signal(SIGINT, SIG_IGN) != (void(*)())SIG_IGN)
272*0Sstevel@tonic-gate 			signal(SIGINT, onintr);
273*0Sstevel@tonic-gate 		printf ("%s ", fname);
274*0Sstevel@tonic-gate 		pw = getpwuid (sbuf.st_uid);
275*0Sstevel@tonic-gate 		if (pw)
276*0Sstevel@tonic-gate 			printf ("(%s)", pw->pw_name);
277*0Sstevel@tonic-gate 		else
278*0Sstevel@tonic-gate 			printf (".....");
279*0Sstevel@tonic-gate 		cftime(time_buf, DATE_FMT, &sbuf.st_mtime);
280*0Sstevel@tonic-gate 		printf (" %s\n", time_buf);
281*0Sstevel@tonic-gate 		op = 0;
282*0Sstevel@tonic-gate 		ip = INDENT;
283*0Sstevel@tonic-gate 		while ((c = getc (fd)) != EOF) {
284*0Sstevel@tonic-gate 			switch (c) {
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 			case '\r':
287*0Sstevel@tonic-gate 			case '\n':
288*0Sstevel@tonic-gate 				putchar (c);
289*0Sstevel@tonic-gate 				op = 0;
290*0Sstevel@tonic-gate 				ip = INDENT;
291*0Sstevel@tonic-gate 				break;
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 			case ' ':
294*0Sstevel@tonic-gate 				ip++;
295*0Sstevel@tonic-gate 				break;
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate 			case '\b':
298*0Sstevel@tonic-gate 				if (ip > INDENT)
299*0Sstevel@tonic-gate 					ip--;
300*0Sstevel@tonic-gate 				break;
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 			case '\t':
303*0Sstevel@tonic-gate 				ip = ((ip - INDENT + 8) & -8) + INDENT;
304*0Sstevel@tonic-gate 				break;
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 			default:
307*0Sstevel@tonic-gate 				while (ip < op) {
308*0Sstevel@tonic-gate 					putchar ('\b');
309*0Sstevel@tonic-gate 					op--;
310*0Sstevel@tonic-gate 				}
311*0Sstevel@tonic-gate 				while ((ip & -8) > (op & -8)) {
312*0Sstevel@tonic-gate 					putchar ('\t');
313*0Sstevel@tonic-gate 					op = (op + 8) & -8;
314*0Sstevel@tonic-gate 				}
315*0Sstevel@tonic-gate 				while (ip > op) {
316*0Sstevel@tonic-gate 					putchar (' ');
317*0Sstevel@tonic-gate 					op++;
318*0Sstevel@tonic-gate 				}
319*0Sstevel@tonic-gate 				putchar (c);
320*0Sstevel@tonic-gate 				ip++;
321*0Sstevel@tonic-gate 				op++;
322*0Sstevel@tonic-gate 				break;
323*0Sstevel@tonic-gate 			}
324*0Sstevel@tonic-gate 		}
325*0Sstevel@tonic-gate 		fflush (stdout);
326*0Sstevel@tonic-gate finish:
327*0Sstevel@tonic-gate 		putchar ('\n');
328*0Sstevel@tonic-gate 		fclose (fd);
329*0Sstevel@tonic-gate 		number_read++;
330*0Sstevel@tonic-gate 		if (signal(SIGINT, SIG_IGN) != (void(*)())SIG_IGN)
331*0Sstevel@tonic-gate 			signal(SIGINT, SIG_DFL);
332*0Sstevel@tonic-gate 	}
333*0Sstevel@tonic-gate }
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate late_news (emit, update)
336*0Sstevel@tonic-gate 	int (*emit)(), update;
337*0Sstevel@tonic-gate {
338*0Sstevel@tonic-gate 	long cutoff;
339*0Sstevel@tonic-gate 	int i;
340*0Sstevel@tonic-gate 	char fname[50], *cp;
341*0Sstevel@tonic-gate 	struct stat newstime;
342*0Sstevel@tonic-gate 	int fd;
343*0Sstevel@tonic-gate 	struct {
344*0Sstevel@tonic-gate 		long actime, modtime;
345*0Sstevel@tonic-gate 	} utb;
346*0Sstevel@tonic-gate 	extern char *getenv();
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	/* Determine the time when last called */
349*0Sstevel@tonic-gate 	cp = getenv ("HOME");
350*0Sstevel@tonic-gate 	if (cp == NULL) {
351*0Sstevel@tonic-gate 		fprintf (stderr, "Cannot find HOME variable\n");
352*0Sstevel@tonic-gate 		exit (1);
353*0Sstevel@tonic-gate 	}
354*0Sstevel@tonic-gate 	strcpy (fname, cp);
355*0Sstevel@tonic-gate 	strcat (fname, "/");
356*0Sstevel@tonic-gate 	strcat (fname, ".news_time");
357*0Sstevel@tonic-gate 	cutoff = stat (fname, &newstime) < 0? 0: newstime.st_mtime;
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 	/* Print the recent items */
360*0Sstevel@tonic-gate 	for (i=0; i<n_count && n_list[i].n_time > cutoff; i++) {
361*0Sstevel@tonic-gate 		(*emit) (n_list[i].n_name);
362*0Sstevel@tonic-gate 		number_read++;
363*0Sstevel@tonic-gate 	}
364*0Sstevel@tonic-gate 	(*emit) ((char *) NULL);
365*0Sstevel@tonic-gate 	fflush (stdout);
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 	if (update) {
368*0Sstevel@tonic-gate 		/* Re-create the file and refresh the update time */
369*0Sstevel@tonic-gate 		if (n_count > 0 && (fd = creat (fname, RD_WR_ALL)) >= 0) {
370*0Sstevel@tonic-gate 			utb.actime = utb.modtime = n_list[0].n_time;
371*0Sstevel@tonic-gate 			close (fd);
372*0Sstevel@tonic-gate 			utime (fname, &utb);
373*0Sstevel@tonic-gate 		}
374*0Sstevel@tonic-gate 	}
375*0Sstevel@tonic-gate }
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate notify (s)
378*0Sstevel@tonic-gate 	char *s;
379*0Sstevel@tonic-gate {
380*0Sstevel@tonic-gate 	static int first = 1;
381*0Sstevel@tonic-gate 
382*0Sstevel@tonic-gate 	if (s) {
383*0Sstevel@tonic-gate 		if (first) {
384*0Sstevel@tonic-gate 			first = 0;
385*0Sstevel@tonic-gate 			printf ("news:", NEWS);
386*0Sstevel@tonic-gate 		}
387*0Sstevel@tonic-gate 		printf (" %.14s", s);
388*0Sstevel@tonic-gate 	} else if (!first)
389*0Sstevel@tonic-gate 		putchar ('\n');
390*0Sstevel@tonic-gate }
391*0Sstevel@tonic-gate 
392*0Sstevel@tonic-gate /*ARGSUSED*/
393*0Sstevel@tonic-gate count (s)
394*0Sstevel@tonic-gate 	char *s;
395*0Sstevel@tonic-gate {
396*0Sstevel@tonic-gate 	static int nitems = 0;
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate 	if (s)
399*0Sstevel@tonic-gate 		nitems++;
400*0Sstevel@tonic-gate 	else {
401*0Sstevel@tonic-gate 		if (nitems) {
402*0Sstevel@tonic-gate 			printf ("%d news item", nitems);
403*0Sstevel@tonic-gate 			if (nitems != 1)
404*0Sstevel@tonic-gate 				putchar ('s');
405*0Sstevel@tonic-gate 			printf (".\n");
406*0Sstevel@tonic-gate 		}
407*0Sstevel@tonic-gate 		else printf("No news.\n");
408*0Sstevel@tonic-gate 	}
409*0Sstevel@tonic-gate }
410*0Sstevel@tonic-gate 
411*0Sstevel@tonic-gate void
412*0Sstevel@tonic-gate onintr()
413*0Sstevel@tonic-gate {
414*0Sstevel@tonic-gate 	sleep(2);
415*0Sstevel@tonic-gate 	longjmp(save_addr, 1);
416*0Sstevel@tonic-gate }
417*0Sstevel@tonic-gate ck_num()
418*0Sstevel@tonic-gate {
419*0Sstevel@tonic-gate 	if (sopt && !number_read) printf("No news.\n");
420*0Sstevel@tonic-gate 	return(0);
421*0Sstevel@tonic-gate }
422*0Sstevel@tonic-gate 
423