|
|
1.1 root 1: /*
2: * checknews - news checking program
3: */
4:
5: static char *SccsId = "@(#)checknews.c 2.15 5/3/83";
6:
7: #include <stdio.h>
8: #include <sys/types.h>
9: #include <pwd.h>
10: #include <ctype.h>
11:
12: #include "defs.h"
13: #include "header.h"
14:
15: char bfr[BUFLEN]; /* general-use scratch area */
16: char optbuf[BUFLEN]; /* NEWSOPTS buffer */
17: char username[BUFLEN]; /* user's login name */
18: char userhome[BUFLEN]; /* user's home directory */
19: char SPOOL[BUFLEN]; /* spool directory */
20: char LIB[BUFLEN]; /* library directory */
21: char ACTIVE[BUFLEN]; /* active newsgroups file */
22: char *NEWSU = NEWSUSR; /* login name for netnews */
23: char *NEWSG = NEWSGRP; /* group name for netnews */
24: int line = -1, y, e, n, q;
25: int verbose; /* For debugging. */
26: FILE *rcfp,*actfp;
27: char newsrc[BUFLEN],*rcline[LINES],rcbuf[LBUFLEN],*argvrc[LINES];
28: struct passwd *getpwuid();
29: char *malloc(),*getenv(), *index();
30: struct hbuf header;
31: char coptbuf[BUFLEN],datebuf[BUFLEN];
32: int mode = 1;
33: #ifndef SHELL
34: char *SHELL;
35: #endif
36:
37: main(argc, argv)
38: int argc;
39: register char **argv;
40: {
41: register char *ptr; /* pointer to rest of buffer */
42: char *user, *home;
43: struct passwd *pw;
44: struct group *gp;
45: int sflag = 0, optflag = FALSE, space = FALSE;
46: int i;
47:
48: y = 0;
49: n = 0;
50: e = 0;
51: q = 0;
52: pathinit();
53: if (--argc > 0) {
54: for (argv++; **argv; ++*argv) {
55: switch(**argv) {
56: case 'y':
57: y++;
58: break;
59: case 'q':
60: q++;
61: break;
62: case 'v':
63: verbose++;
64: break;
65: case 'n':
66: n++;
67: break;
68: case 'e':
69: case 'f':
70: e++;
71: break;
72: }
73: }
74: }
75: if (!n && !e && !y && !q)
76: y++;
77:
78: #ifndef V6
79: if ((user = getenv("USER")) == NULL)
80: user = getenv("LOGNAME");
81: if ((home = getenv("HOME")) == NULL)
82: home = getenv("LOGDIR");
83: if (user == NULL || home == NULL)
84: getuser();
85: else {
86: strcpy(username, user);
87: strcpy(userhome, home);
88: }
89: if (ptr = getenv("NEWSOPTS"))
90: strcpy(rcbuf, ptr);
91: else
92: *rcbuf = '\0';
93: if (*rcbuf) {
94: strcat(rcbuf, " \1");
95: ptr = rcbuf;
96: while (*++ptr)
97: if (isspace(*ptr))
98: *ptr = '\0';
99: for (ptr = rcbuf;; ptr++) {
100: if (!*ptr)
101: continue;
102: if (*ptr == '\1')
103: break;
104: if (++line > LINES)
105: xerror("Too many options.\n");
106: if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL)
107: xerror("Not enough memory.\n");
108: argvrc[line] = rcline[line];
109: strcpy(rcline[line], ptr);
110: while (*ptr)
111: ptr++;
112: }
113: }
114: #else
115: getuser();
116: #endif
117: ptr = getenv("NEWSRC");
118: if (ptr == NULL)
119: sprintf(newsrc, "%s/%s", userhome, NEWSRC);
120: else
121: strcpy(newsrc, ptr);
122: if ((rcfp = fopen(newsrc, "r")) != NULL) {
123: while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
124: if (!(space = isspace(*rcbuf)))
125: optflag = FALSE;
126: if (!strncmp(rcbuf, "options ", 8))
127: optflag = TRUE;
128: if (optflag) {
129: strcat(rcbuf, "\1");
130: if (space)
131: ptr = rcbuf - 1;
132: else
133: ptr = &rcbuf[7];
134: while (*++ptr)
135: if (isspace(*ptr))
136: *ptr = '\0';
137: if (space)
138: ptr = rcbuf;
139: else
140: ptr = &rcbuf[8];
141: for (;; ptr++) {
142: if (!*ptr)
143: continue;
144: if (*ptr == '\1')
145: break;
146: if (++line > LINES)
147: xerror("Too many options.\n");
148: if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL)
149: xerror("Not enough memory.\n");
150: argvrc[line] = rcline[line];
151: strcpy(rcline[line], ptr);
152: while (*ptr)
153: ptr++;
154: }
155: }
156: }
157: fclose(rcfp);
158: }
159: header.nbuf[0] = 0;
160: if (line != -1) {
161: #ifdef DEBUG
162: for (i = 0; i <= line; i++)
163: fprintf(stderr, "options: %s\n", rcline[i]);
164: #endif
165: process(line+2, argvrc);
166: do {
167: #ifdef DEBUG
168: fprintf(stderr, "Freeing %d\n", line);
169: #endif
170: free(rcline[line]);
171: } while (line--);
172: }
173:
174: if (!*header.nbuf) {
175: strcpy(header.nbuf, DFLTSUB);
176: ngcat(header.nbuf);
177: }
178: strcat(header.nbuf, ADMSUB);
179: ngcat(header.nbuf);
180: if (*header.nbuf)
181: lcase(header.nbuf);
182: makehimask(header.nbuf, "junk");
183: makehimask(header.nbuf, "control");
184: makehimask(header.nbuf, "test");
185: if (access(newsrc, 0)) {
186: if (verbose>1)
187: printf("No newsrc\n");
188: yep(argv);
189: }
190: if ((rcfp = fopen(newsrc, "r")) == NULL)
191: xerror("Cannot open .newsrc file");
192: while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
193: if (!nstrip(rcbuf))
194: xerror(".newsrc line too long");
195: if (++line >= LINES)
196: xerror("Too many .newsrc lines");
197: if ((rcline[line] = malloc(strlen(rcbuf)+1)) == NULL)
198: xerror("Not enough memory");
199: strcpy(rcline[line], rcbuf);
200: }
201: if ((actfp = fopen(ACTIVE, "r")) == NULL)
202: xerror("Cannot open active newsgroups file");
203:
204: #ifdef DEBUG
205: fprintf(stderr, "header.nbuf = %s\n", header.nbuf);
206: #endif
207: nchk(argv);
208: exit(0);
209: }
210:
211: nchk(argv)
212: char **argv;
213: {
214: register int i;
215: register char *ptr;
216: int l;
217: long narts;
218: char saveptr;
219: char aline[100];
220:
221: #ifdef DEBUG
222: fprintf(stderr, "nchk()\n");
223: #endif
224: while (fgets(aline, sizeof aline, actfp) != NULL) {
225: sscanf(aline, "%s %ld", bfr, &narts);
226: #ifdef DEBUG
227: fprintf(stderr, "bfr = '%s'\n", bfr);
228: #endif
229: ngcat(bfr);
230: if (!ngmatch(bfr, header.nbuf))
231: continue;
232: ngdel(bfr);
233: i = findrcline(bfr);
234: if (i < 0) {
235: if (verbose>1)
236: printf("No newsrc line for newsgroup %s\n", bfr);
237: strcpy(rcbuf, " 0");
238: } else
239: strcpy(rcbuf, rcline[i]);
240: ptr = rcbuf;
241:
242: if (index(rcbuf, '!') != NULL)
243: continue;
244: if (index(rcbuf, ',') != NULL) {
245: if (verbose>1)
246: printf("Comma in %s newsrc line\n", bfr);
247: yep(argv);
248: }
249: while (*ptr)
250: ptr++;
251: while (!isdigit(*--ptr) && ptr >= rcbuf)
252: ;
253: if (ptr < rcbuf) {
254: if (verbose>1)
255: printf("Ran off beginning of %s newsrc line.\n", bfr);
256: yep(argv);
257: }
258: while (isdigit(*--ptr))
259: ;
260: sscanf(++ptr, "%d", &l);
261: if (narts > l) {
262: if (verbose) {
263: printf("News: %s ...\n", bfr);
264: if (verbose < 2)
265: y = 0;
266: }
267: yep(argv);
268: }
269: contin:;
270: }
271: if (n)
272: printf("No news is good news.\n");
273: }
274:
275: yep(argv)
276: char **argv;
277: {
278: if (y)
279: if (verbose)
280: printf("There is probably news.\n");
281: else
282: printf("There is news.\n");
283: if (e) {
284: #ifdef V6
285: execv("/usr/bin/readnews", argv);
286: #else
287: execvp("readnews", argv);
288: #endif
289: fprintf(stderr, "Cannot exec readnews.\n");
290: }
291: if (q)
292: exit(1);
293: else
294: exit(0);
295: }
296:
297: xerror(message, arg1, arg2)
298: char *message;
299: int arg1, arg2;
300: {
301: char buffer[128];
302:
303: sprintf(buffer, message, arg1, arg2);
304: fprintf(stderr, "checknews: %s.\n", buffer);
305: exit(1);
306: }
307:
308: /*
309: * Append NGDELIM to string.
310: */
311: ngcat(s)
312: register char *s;
313: {
314: if (*s) {
315: while (*s++);
316: s -= 2;
317: if (*s++ == NGDELIM)
318: return;
319: }
320: *s++ = NGDELIM;
321: *s = '\0';
322: }
323:
324: /*
325: * News group matching.
326: *
327: * nglist is a list of newsgroups.
328: * sublist is a list of subscriptions.
329: * sublist may have "meta newsgroups" in it.
330: * All fields are NGDELIM separated,
331: * and there is an NGDELIM at the end of each argument.
332: *
333: * Currently implemented glitches:
334: * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
335: * If subscription X matches Y, it also matches Y.anything.
336: */
337: ngmatch(nglist, sublist)
338: register char *nglist, *sublist;
339: {
340: register char *n, *s;
341: register int rc;
342:
343: rc = FALSE;
344: for (n = nglist; *n != '\0' && rc == FALSE;) {
345: for (s = sublist; *s != '\0';) {
346: if (*s != NEGCHAR)
347: rc |= ptrncmp(s, n);
348: else
349: rc &= ~ptrncmp(s+1, n);
350: while (*s++ != NGDELIM);
351: }
352: while (*n++ != NGDELIM);
353: }
354: return(rc);
355: }
356:
357: /*
358: * Compare two newsgroups for equality.
359: * The first one may be a "meta" newsgroup.
360: */
361: ptrncmp(ng1, ng2)
362: register char *ng1, *ng2;
363: {
364: while (*ng1 != NGDELIM) {
365: if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') {
366: ng1 += 3;
367: while (*ng2 != NGDELIM && *ng2 != '.')
368: if (ptrncmp(ng1, ng2++))
369: return(TRUE);
370: return (ptrncmp(ng1, ng2));
371: } else if (*ng1++ != *ng2++)
372: return(FALSE);
373: }
374: return (*ng2 == '.' || *ng2 == NGDELIM);
375: }
376:
377: /*
378: * Get user name and home directory.
379: */
380: getuser()
381: {
382: static int flag = TRUE;
383: register struct passwd *p;
384:
385: if (flag) {
386: if ((p = getpwuid(getuid())) == NULL)
387: xerror("Cannot get user's name");
388: if (username[0] == 0)
389: strcpy(username, p->pw_name);
390: strcpy(userhome, p->pw_dir);
391: flag = FALSE;
392: }
393: }
394:
395: /*
396: * Strip trailing newlines, blanks, and tabs from 's'.
397: * Return TRUE if newline was found, else FALSE.
398: */
399: nstrip(s)
400: register char *s;
401: {
402: register char *p;
403: register int rc;
404:
405: rc = FALSE;
406: p = s;
407: while (*p)
408: if (*p++ == '\n')
409: rc = TRUE;
410: while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
411: *++p = '\0';
412: return(rc);
413: }
414:
415: /*
416: * Delete trailing NGDELIM.
417: */
418: ngdel(s)
419: register char *s;
420: {
421: if (*s++) {
422: while (*s++);
423: s -= 2;
424: if (*s == NGDELIM)
425: *s = '\0';
426: }
427: }
428:
429: lcase(s)
430: register char *s;
431: {
432: register char *ptr;
433:
434: for (ptr = s; *ptr; ptr++)
435: if (isupper(*ptr))
436: *ptr = tolower(*ptr);
437: }
438:
439: /*
440: * finds the line in your .newsrc file (actually the in-core "rcline"
441: * copy of it) and returns the index into the array where it was found.
442: * -1 means it didn't find it.
443: *
444: * We play clever games here to make this faster. It's inherently
445: * quadratic - we spend lots of CPU time here because we search through
446: * the whole .newsrc for each line. The "prev" variable remembers where
447: * the last match was found; we start the search there and loop around
448: * to the beginning, in the hopes that the calls will be roughly in order.
449: */
450: int
451: findrcline(name)
452: char *name;
453: {
454: register char *p, *ptr;
455: register int cur;
456: register int i;
457: register int top;
458: static int prev = 0;
459:
460: top = line; i = prev;
461: loop:
462: for (; i <= top; i++) {
463: for (p = name, ptr = rcline[i]; (cur = *p++); ) {
464: if (cur != *ptr++)
465: goto contin2;
466: }
467: if (*ptr != ':' && *ptr != '!')
468: continue;
469: prev = i;
470: return i;
471: contin2:
472: ;
473: }
474: if (i > line && line > prev-1) {
475: i = 0;
476: top = prev-1;
477: goto loop;
478: }
479: return -1;
480: }
481:
482: /*
483: * Forbid newsgroup ng, unless he asked for it in nbuf.
484: */
485: makehimask(nbuf, ng)
486: char *nbuf, *ng;
487: {
488: if (!findex(nbuf, ng)) {
489: ngcat(nbuf);
490: strcat(nbuf, "!");
491: strcat(nbuf, ng);
492: ngcat(nbuf);
493: }
494: }
495:
496: /*
497: * Return true if the string searchfor is in string, but not if preceeded by !.
498: */
499: findex(string, searchfor)
500: char *string, *searchfor;
501: {
502: register char first;
503: register char *p;
504:
505: first = *searchfor;
506: for (p=index(string, first); p; p = index(p+1, first)) {
507: if (p>string && p[-1] != '!' && strncmp(p, searchfor, strlen(searchfor)) == 0)
508: return TRUE;
509: }
510: return FALSE;
511: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.