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