|
|
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.