|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)misc.c 1.20 (Berkeley) 10/15/87";
3: #endif
4:
5: #include "../common/conf.h"
6:
7: #include "common.h"
8:
9: /*
10: * open_valid_art -- determine if a given article name is valid;
11: * if it is, return a file pointer to the open article,
12: * along with a unique id of the article.
13: *
14: * Parameters: "artname" is a string containing the
15: * name of the article.
16: * "id" is space for us to put the article
17: * id in.
18: *
19: * Returns: File pointer to the open article if the
20: * article is valid; NULL otherwise
21: *
22: * Side effects: None.
23: */
24:
25: FILE *
26: open_valid_art(artname, id)
27: char *artname;
28: char *id;
29: {
30: static int crnt_art_num;
31: static char crnt_art_id[MAX_STRLEN];
32: int fd;
33: struct stat statbuf;
34:
35: if (art_fp != NULL) {
36: if (crnt_art_num == atoi(artname)) {
37: if (fseek(art_fp, (long) 0, 0) < 0)
38: close_crnt();
39: else {
40: (void) strcpy(id, crnt_art_id);
41: return (art_fp);
42: }
43: } else
44: close_crnt();
45: }
46:
47: art_fp = fopen(artname, "r");
48:
49: if (art_fp == NULL)
50: return (NULL);
51:
52: fd = fileno(art_fp);
53:
54: if (fstat(fd, &statbuf) < 0) {
55: close_crnt();
56: return (NULL);
57: }
58:
59: if ((statbuf.st_mode & S_IFREG) != S_IFREG) {
60: close_crnt();
61: return (NULL);
62: }
63:
64: get_id(art_fp, id);
65: (void) strcpy(crnt_art_id, id);
66: crnt_art_num = atoi(artname);
67: return (art_fp);
68: }
69:
70:
71: /*
72: * gethistent -- return the path name of an article if it's
73: * in the history file.
74: *
75: * Parameters: "msg_id" is the message ID of the
76: * article, enclosed in <>'s.
77: *
78: * Returns: A char pointer to a static data area
79: * containing the full pathname of the
80: * article, or NULL if the message-id is not
81: * in thef history file.
82: *
83: * Side effects: opens dbm database
84: * (only once, keeps it open after that).
85: * Converts "msg_id" to lower case.
86: */
87:
88: char *
89: gethistent(msg_id)
90: char *msg_id;
91: {
92: char line[MAX_STRLEN];
93: char *tmp;
94: register char *cp;
95: long ltmp;
96: static char path[MAX_STRLEN];
97: #ifdef DBM
98: static int dbopen = 0;
99: datum fetch();
100: #else
101: static DBM *db = NULL; /* History file, dbm version */
102: #endif
103: static FILE *hfp = NULL; /* history file, text version */
104: datum key, content;
105:
106: #ifdef DBM
107: if (!dbopen) {
108: if (dbminit(historyfile) < 0) {
109: #ifdef SYSLOG
110: syslog(LOG_ERR, "openartbyid: dbminit %s: %m",
111: historyfile);
112: #endif SYSLOG
113: return (NULL);
114: } else
115: dbopen = 1;
116: }
117: #else /* ndbm */
118: if (db == NULL) {
119: db = dbm_open(historyfile, O_RDONLY, 0);
120: if (db == NULL) {
121: #ifdef SYSLOG
122: syslog(LOG_ERR, "openartbyid: dbm_open %s: %m",
123: historyfile);
124: #endif SYSLOG
125: return (NULL);
126: }
127: }
128: #endif DBM
129:
130: for (cp = msg_id; *cp != '\0'; ++cp)
131: if (isupper(*cp))
132: *cp = tolower(*cp);
133:
134: key.dptr = msg_id;
135: key.dsize = strlen(msg_id) + 1;
136:
137: #ifdef DBM
138: content = fetch(key);
139: #else /* ndbm */
140: content = dbm_fetch(db, key);
141: #endif DBM
142: if (content.dptr == NULL)
143: return (NULL);
144:
145: if (hfp == NULL) {
146: hfp = fopen(historyfile, "r");
147: if (hfp == NULL) {
148: #ifdef SYSLOG
149: syslog(LOG_ERR, "message: fopen %s: %m",
150: historyfile);
151: #endif SYSLOG
152: return (NULL);
153: }
154: }
155:
156: bcopy(content.dptr, (char *)<mp, sizeof (long));
157: if (fseek(hfp, ltmp, 0) < 0) {
158: #ifdef SYSLOG
159: syslog(LOG_ERR, "message: fseek: %m");
160: #endif SYSLOG
161: return (NULL);
162: }
163:
164: (void) fgets(line, sizeof(line), hfp);
165: if ((cp = index(line, '\n')) != NULL)
166: *cp = '\0';
167: cp = index(line, '\t');
168: if (cp != NULL)
169: cp = index(cp+1, '\t');
170: if (cp == NULL) {
171: #ifdef SYSLOG
172: syslog(LOG_ERR,
173: "message: malformed line in history file at %ld bytes, id %s",
174: ltmp, msg_id);
175: #endif SYSLOG
176: return (NULL);
177: }
178: tmp = cp+1;
179:
180: if ((cp = index(tmp, ' ')) != NULL)
181: *cp = '\0';
182:
183: while ((cp = index(tmp, '.')) != NULL)
184: *cp = '/';
185:
186: (void) strcpy(path, spooldir);
187: (void) strcat(path, "/");
188: (void) strcat(path, tmp);
189:
190: return (path);
191: }
192:
193: /*
194: * openartbyid -- open an article by message-id.
195: *
196: * Arguments: "msg_id" is the message-id of the article
197: * to open.
198: *
199: * Returns: File pointer to opened article, or NULL if
200: * the article was not in the history file or
201: * could not be opened.
202: *
203: * Side effects: Opens article.
204: */
205:
206: FILE *
207: openartbyid(msg_id)
208: char *msg_id;
209: {
210: char *path;
211:
212: path = gethistent(msg_id);
213: if (path != NULL)
214: return (fopen(path, "r"));
215: else
216: return (NULL);
217: }
218:
219:
220: /*
221: * check_ngperm -- check to see if they're allowed to see this
222: * article by matching Newsgroups: and Distribution: line.
223: *
224: * Parameters: "fp" is the file pointer of this article.
225: *
226: * Returns: 0 if they're not allowed to see it.
227: * 1 if they are.
228: *
229: * Side effects: None.
230: */
231:
232: check_ngperm(fp)
233: register FILE *fp;
234: {
235: char buf[MAX_STRLEN];
236: register char *cp;
237: static char **ngarray;
238: int ngcount;
239:
240: if (ngpermcount == 0)
241: return (1);
242:
243: while (fgets(buf, sizeof (buf), fp) != NULL) {
244: if (buf[0] == '\n') /* End of header */
245: break;
246: if (buf[0] != 'N' && buf[0] != 'n')
247: continue;
248: cp = index(buf, '\n');
249: if (cp)
250: *cp = '\0';
251: cp = index(buf, ':');
252: if (cp == NULL)
253: continue;
254: *cp = '\0';
255: if (streql(buf, "newsgroups")) {
256: ngcount = get_nglist(&ngarray, cp+2);
257: break;
258: }
259: }
260:
261: (void) rewind(fp);
262:
263: if (ngcount == 0) /* Either no newgroups or null entry */
264: return (1);
265:
266: return (ngmatch(strneql, ALLBUT,
267: ngpermlist, ngpermcount, ngarray, ngcount));
268: }
269:
270:
271: /*
272: * spew -- spew out the contents of a file to stdout, doing
273: * the necessary cr-lf additions at the end. Finish with
274: * a "." on a line by itself, and an fflush(stdout).
275: *
276: * Parameters: "how" tells what part of the file we
277: * want spewed:
278: * ARTICLE The entire thing.
279: * HEAD Just the first part.
280: * BODY Just the second part.
281: * "fp" is the open file to spew from.
282: *
283: * Returns: Nothing.
284: *
285: * Side effects: Changes current position in file.
286: */
287:
288: spew(fp, how)
289: FILE *fp;
290: int how;
291: {
292: char line[MAX_STRLEN];
293: register char *cp;
294:
295: #ifdef LOG
296: ++arts_acsd;
297: #endif
298:
299: if (how == STAT) {
300: (void) fflush(stdout);
301: return;
302: }
303:
304: while (fgets(line, sizeof(line)-6, fp) != NULL && *line != '\n') {
305: if (how == BODY) /* We need to skip this anyway */
306: continue;
307: cp = index(line, '\n');
308: if (cp != NULL)
309: *cp = '\0';
310: if (*line == '.')
311: putchar('.');
312: putline(line);
313: if (cp == NULL) {
314: for (;;) {
315: if ((fgets(line, sizeof(line)-6, fp) == NULL)
316: || (index(line, '\n') != NULL))
317: break;
318: }
319: }
320: }
321:
322: if (how == HEAD) {
323: putchar('.');
324: putchar('\r');
325: putchar('\n');
326: (void) fflush(stdout);
327: return;
328: } else if (how == ARTICLE) {
329: putchar('\r');
330: putchar('\n');
331: }
332:
333: while (fgets(line, sizeof(line)-6, fp) != NULL) {
334: cp = index(line, '\n');
335: if (cp != NULL)
336: *cp = '\0';
337: if (*line == '.')
338: putchar('.');
339: putline(line);
340:
341: if (cp == NULL) {
342: for (;;) {
343: if ((fgets(line, sizeof(line)-6, fp) == NULL)
344: || (index(line, '\n') != NULL))
345: break;
346: }
347: }
348: }
349: putchar('.');
350: putchar('\r');
351: putchar('\n');
352: (void) fflush(stdout);
353: }
354:
355:
356: /*
357: * get_id -- get the message id of the current article.
358: *
359: * Parameters: "art_fp" is a pointer to the open file.
360: * "id" is space for the message ID.
361: *
362: * Returns: Nothing.
363: *
364: * Side effects: Seeks and rewinds on "art_fp".
365: * Changes space pointed to by "id".
366: */
367:
368: get_id(art_fp, id)
369: register FILE *art_fp;
370: char *id;
371: {
372: char line[MAX_STRLEN];
373: register char *cp;
374:
375: while (fgets(line, sizeof(line), art_fp) != NULL) {
376: if (*line == '\n')
377: break;
378: if (*line == 'M' || *line == 'm') { /* "Message-ID" */
379: if ((cp = index(line, ' ')) != NULL) {
380: *cp = '\0';
381: if (streql(line, "Message-ID:")) {
382: (void) strcpy(id, cp + 1);
383: if ((cp = index(id, '\n')) != NULL)
384: *cp = '\0';
385: (void) rewind(art_fp);
386: return;
387: }
388: }
389: }
390: }
391: (void) rewind(art_fp);
392: (void) strcpy(id, "<0>");
393: }
394:
395:
396: /*
397: * close_crnt -- close the current article file pointer, if it's
398: * open.
399: *
400: * Parameters: None.
401: *
402: * Returns: Nothing.
403: *
404: * Side effects: Closes "art_fp" if it's open; sets "art_fp" to NULL.
405: */
406:
407: close_crnt()
408: {
409: if (art_fp != NULL)
410: (void) fclose(art_fp);
411: art_fp = NULL;
412: }
413:
414:
415: /*
416: * findart -- find an article number in the article array.
417: *
418: * Parameters: "artname" is a string containing
419: * the name of the article.
420: *
421: * Returns: An index into "art_array",
422: * or -1 if "artname" isn't in "art_array".
423: *
424: * Side effects: None.
425: *
426: * Improvement: Replace this linear search with a binary one.
427: */
428:
429: findart(artname)
430: char *artname;
431: {
432: register int i, artnum;
433:
434: artnum = atoi(artname);
435:
436: for (i = 0; i < num_arts; ++i)
437: if (art_array[i] == artnum)
438: return(i);
439:
440: return (-1);
441: }
442:
443:
444: /*
445: * get_distlist -- return a nicely set up array of distribution groups
446: * along with a count, when given an NNTP-spec distribution list
447: * in the form <dist1,dist2,...,distn>.
448: *
449: * Parameters: "array" is storage for our array,
450: * set to point at some static data.
451: * "list" is the NNTP distribution list.
452: *
453: * Returns: Number of distributions found.
454: * -1 on error.
455: *
456: * Side effects: Changes static data area.
457: */
458:
459: get_distlist(array, list)
460: char ***array;
461: char *list;
462: {
463: char *cp;
464: int distcount;
465: static char **dist_list = (char **) NULL;
466:
467: if (list[0] != '<')
468: return (-1);
469:
470: cp = index(list + 1, '>');
471: if (cp != NULL)
472: *cp = '\0';
473: else
474: return (-1);
475:
476: for (cp = list + 1; *cp != '\0'; ++cp)
477: if (*cp == ',')
478: *cp = ' ';
479: distcount = parsit(list + 1, &dist_list);
480: *array = dist_list;
481: return (distcount);
482: }
483:
484:
485: /*
486: * streql -- determine if two strings are equal, ignoring case.
487: *
488: * Parameters: "a" and "b" are the pointers
489: * to characters to be compared.
490: *
491: * Returns: 1 if the strings are equal, 0 otherwise.
492: *
493: * Side effects: None.
494: */
495:
496: streql(a, b)
497: register char *a, *b;
498: {
499: char lower();
500:
501: while (lower(*a) == lower(*b)) {
502: if (*a == '\0')
503: return (1);
504: a++;
505: b++;
506: }
507: return (0);
508: }
509:
510:
511: /*
512: * lower -- convert a character to lower case, if it's upper case.
513: *
514: * Parameters: "c" is the character to be
515: * converted.
516: *
517: * Returns: "c" if the character is not
518: * upper case, otherwise the lower
519: * case eqivalent of "c".
520: *
521: * Side effects: None.
522: */
523:
524: char lower(c)
525: register char c;
526: {
527: if (isascii(c) && isupper(c))
528: c = c - 'A' + 'a';
529: return (c);
530: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.