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