|
|
researchv10 Norman
/*
* news foo prints /usr/news/foo
* news -a prints all news items, latest first
* news -n lists names of new items
* news -s tells count of new items only
* news prints items changed since last news
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <setjmp.h>
#include <signal.h>
#include <ndir.h>
#include <pwd.h>
/*
* The following items should not be printed.
*/
char *ignore[] = {
"core",
"dead.letter",
NULL
};
struct n_file {
long n_time;
char n_name[MAXNAMLEN];
} *n_list;
char NEWS[] = "/usr/news";
int n_count;
char stdbuf[BUFSIZ];
jmp_buf save_addr;
main (argc, argv)
int argc;
char **argv;
{
int print_item(), notify(), count();
setbuf (stdout, stdbuf);
initialize();
read_dir();
if (argc <= 1)
late_news (print_item, 1);
else if ( argc == 2 && argv[1][0] == '-'
&& argv[1][1] != '\0' && argv[1][2] == '\0')
switch (argv[1][1]) {
case 'a':
all_news();
break;
case 'n':
late_news (notify, 0);
break;
case 's':
late_news (count, 0);
break;
default:
fprintf (stderr, "news: bad option %s\n", argv[1]);
exit (1);
}
else {
int i;
for (i=1; i<argc; i++)
print_item (argv[i]);
}
return 0;
}
/*
* read_dir: get the file names and modification dates for the
* files in /usr/news into n_list; sort them in reverse by
* modification date. We assume /usr/news is the working directory.
*/
read_dir()
{
struct direct *nf;
struct stat sbuf;
char fname[MAXNAMLEN];
DIR *dirp;
int i, j;
char *malloc(), *realloc();
/* Open the current directory */
if ((dirp = opendir(".")) == NULL) {
fprintf (stderr, "news: ");
perror (NEWS);
exit (1);
}
/* Read the file names into n_list */
n_count = 0;
while (nf = readdir(dirp)) {
strncpy (fname, nf->d_name, (unsigned) strlen(nf->d_name) + 1);
if (nf->d_ino != 0 && stat (fname, &sbuf) >= 0
&& (sbuf.st_mode & S_IFMT) == S_IFREG) {
register char **p;
p = ignore;
while (*p && strncmp (*p, nf->d_name, MAXNAMLEN))
++p;
if (!*p) {
if (n_count++ > 0)
n_list = (struct n_file *)
realloc ((char *) n_list,
(unsigned)
(sizeof (struct n_file)
* n_count));
else
n_list = (struct n_file *) malloc
((unsigned)
(sizeof (struct n_file) *
n_count));
if (n_list == NULL) {
fprintf (stderr, "news: no storage\n");
exit (1);
}
n_list[n_count-1].n_time = sbuf.st_mtime;
strncpy (n_list[n_count-1].n_name,
nf->d_name, MAXNAMLEN);
}
}
}
/* Sort the elements of n_list in decreasing time order */
for (i=1; i<n_count; i++)
for (j=0; j<i; j++)
if (n_list[j].n_time < n_list[i].n_time) {
struct n_file temp;
temp = n_list[i];
n_list[i] = n_list[j];
n_list[j] = temp;
}
/* Clean up */
closedir(dirp);
}
initialize()
{
extern _exit();
if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
signal (SIGQUIT, _exit);
umask (022);
if (chdir (NEWS) < 0) {
fprintf (stderr, "news: ");
perror (NEWS);
exit (1);
}
}
all_news()
{
int i;
for (i=0; i<n_count; i++)
print_item (n_list[i].n_name);
}
print_item (f)
char *f;
{
FILE *fd;
char fname[MAXNAMLEN+1];
static int firstitem = 1;
int onintr();
struct passwd *getpwuid();
if (f == NULL) {
return;
}
strncpy (fname, f, MAXNAMLEN);
fname[MAXNAMLEN] = '\0';
if ((fd = fopen (fname, "r")) == NULL) {
fprintf (stderr, "news: %s/", NEWS);
perror (fname);
} else {
register int c, ip, op;
struct stat sbuf;
char *ctime();
struct passwd *pw;
fstat (fileno (fd), &sbuf);
if (firstitem) {
firstitem = 0;
putchar ('\n');
}
if (setjmp(save_addr))
goto finish;
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, onintr);
printf ("%s ", fname);
pw = getpwuid (sbuf.st_uid);
if (pw)
printf ("(%s)", pw->pw_name);
else
printf (".....");
printf (" %s\n", ctime (&sbuf.st_mtime));
/*
* copy the news item to the standard output
*
* ip is the output character position corresponding
* to the present input character. op is the
* actual current output character position.
*/
while ((c = getc (fd)) != EOF)
putchar (c);
fflush (stdout);
finish:
putchar ('\n');
fclose (fd);
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, SIG_DFL);
}
}
late_news (emit, update)
int (*emit)(), update;
{
long cutoff;
int i;
char fname[50], *getenv(), *cp;
struct stat newstime;
int fd;
struct {
long actime, modtime;
} utb;
/* Determine the time when last called */
cp = getenv ("HOME");
if (cp == NULL) {
fprintf (stderr, "news: cannot find HOME variable\n");
exit (1);
}
strcpy (fname, cp);
strcat (fname, "/");
strcat (fname, ".news_time");
cutoff = stat (fname, &newstime) < 0? 0: newstime.st_mtime;
/* Print the recent items */
for (i=0; i<n_count && n_list[i].n_time > cutoff; i++)
(*emit) (n_list[i].n_name);
(*emit) ((char *) NULL);
fflush (stdout);
if (update) {
/* Re-create the file and refresh the update time */
if (n_count > 0 && (fd = creat (fname, 0666)) >= 0) {
utb.actime = utb.modtime = n_list[0].n_time;
close (fd);
utime (fname, &utb);
}
}
}
notify (s)
char *s;
{
static int first = 1;
if (s) {
if (first) {
first = 0;
printf ("news:", NEWS);
}
printf (" %.14s", s);
} else if (!first)
putchar ('\n');
}
/*ARGSUSED*/
count (s)
char *s;
{
static int nitems = 0;
if (s)
nitems++;
else if (nitems) {
printf ("%d news item", nitems);
if (nitems > 1)
putchar ('s');
printf (".\n");
}
}
onintr()
{
sleep(2);
longjmp(save_addr, 1);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.