#ifndef lint static char *sccsid = "@(#)misc.c 1.25 (Berkeley) 2/6/88"; #endif #include "../common/conf.h" #include "common.h" /* * open_valid_art -- determine if a given article name is valid; * if it is, return a file pointer to the open article, * along with a unique id of the article. * * Parameters: "artname" is a string containing the * name of the article. * "id" is space for us to put the article * id in. * * Returns: File pointer to the open article if the * article is valid; NULL otherwise * * Side effects: None. */ FILE * open_valid_art(artname, id) char *artname; char *id; { static int crnt_art_num; static char crnt_art_id[MAXBUFLEN]; int fd; struct stat statbuf; if (art_fp != NULL) { if (crnt_art_num == atoi(artname)) { if (fseek(art_fp, (long) 0, 0) < 0) close_crnt(); else { (void) strcpy(id, crnt_art_id); return (art_fp); } } else close_crnt(); } art_fp = fopen(artname, "r"); if (art_fp == NULL) return (NULL); fd = fileno(art_fp); if (fstat(fd, &statbuf) < 0) { close_crnt(); return (NULL); } if ((statbuf.st_mode & S_IFREG) != S_IFREG) { close_crnt(); return (NULL); } get_id(art_fp, id); (void) strcpy(crnt_art_id, id); crnt_art_num = atoi(artname); return (art_fp); } /* * gethistent -- return the path name of an article if it's * in the history file. * * Parameters: "msg_id" is the message ID of the * article, enclosed in <>'s. * * Returns: A char pointer to a static data area * containing the full pathname of the * article, or NULL if the message-id is not * in thef history file. * * Side effects: opens dbm database * (only once, keeps it open after that). * Converts "msg_id" to lower case. */ #ifndef NDBM # ifndef DBM # ifndef USGHIST # define USGHIST # endif not USGHIST # endif not DBM #endif not DBM char * gethistent(msg_id) char *msg_id; { char line[MAXBUFLEN]; char *tmp; register char *cp; long ltmp; static char path[MAXPATHLEN]; #ifdef USGHIST char *histfile(); register int len; #else not USGHIST #ifdef DBM static int dbopen = 0; datum fetch(); #else not DBM static DBM *db = NULL; /* History file, dbm version */ #endif DBM datum key, content; #endif USGHIST static FILE *hfp = NULL; /* history file, text version */ for (cp = msg_id; *cp != '\0'; ++cp) if (isupper(*cp)) *cp = tolower(*cp); #ifdef USGHIST hfp = fopen(histfile(msg_id), "r"); if (hfp == NULL) { #ifdef SYSLOG syslog(LOG_ERR, "gethistent: histfile: %m"); #endif SYSLOG return (NULL); } len = strlen(msg_id); while (fgets(line, sizeof (line), hfp)) if (!strncasecmp(msg_id, line, len)) break; if (feof(hfp)) { (void) fclose(hfp); return (NULL); } #else not USGHIST #ifdef DBM if (!dbopen) { if (dbminit(historyfile) < 0) { #ifdef SYSLOG syslog(LOG_ERR, "openartbyid: dbminit %s: %m", historyfile); #endif SYSLOG return (NULL); } else dbopen = 1; } #else /* ndbm */ if (db == NULL) { db = dbm_open(historyfile, O_RDONLY, 0); if (db == NULL) { #ifdef SYSLOG syslog(LOG_ERR, "openartbyid: dbm_open %s: %m", historyfile); #endif SYSLOG return (NULL); } } #endif DBM key.dptr = msg_id; key.dsize = strlen(msg_id) + 1; #ifdef DBM content = fetch(key); #else /* ndbm */ content = dbm_fetch(db, key); #endif DBM if (content.dptr == NULL) return (NULL); if (hfp == NULL) { hfp = fopen(historyfile, "r"); if (hfp == NULL) { #ifdef SYSLOG syslog(LOG_ERR, "message: fopen %s: %m", historyfile); #endif SYSLOG return (NULL); } } bcopy(content.dptr, (char *)<mp, sizeof (long)); if (fseek(hfp, ltmp, 0) < 0) { #ifdef SYSLOG syslog(LOG_ERR, "message: fseek: %m"); #endif SYSLOG return (NULL); } (void) fgets(line, sizeof(line), hfp); #endif USGHIST if ((cp = index(line, '\n')) != NULL) *cp = '\0'; cp = index(line, '\t'); if (cp != NULL) cp = index(cp+1, '\t'); if (cp == NULL) { #ifdef SYSLOG syslog(LOG_ERR, "message: malformed line in history file at %ld bytes, id %s", ltmp, msg_id); #endif SYSLOG return (NULL); } tmp = cp+1; if ((cp = index(tmp, ' ')) != NULL) *cp = '\0'; while ((cp = index(tmp, '.')) != NULL) *cp = '/'; (void) strcpy(path, spooldir); (void) strcat(path, "/"); (void) strcat(path, tmp); return (path); } /* * openartbyid -- open an article by message-id. * * Arguments: "msg_id" is the message-id of the article * to open. * * Returns: File pointer to opened article, or NULL if * the article was not in the history file or * could not be opened. * * Side effects: Opens article. */ FILE * openartbyid(msg_id) char *msg_id; { char *path; path = gethistent(msg_id); if (path != NULL) return (fopen(path, "r")); else return (NULL); } /* * check_ngperm -- check to see if they're allowed to see this * article by matching Newsgroups: and Distribution: line. * * Parameters: "fp" is the file pointer of this article. * * Returns: 0 if they're not allowed to see it. * 1 if they are. * * Side effects: None. */ check_ngperm(fp) register FILE *fp; { char buf[MAXBUFLEN]; register char *cp; static char **ngarray; int ngcount; if (ngpermcount == 0) return (1); while (fgets(buf, sizeof (buf), fp) != NULL) { if (buf[0] == '\n') /* End of header */ break; if (buf[0] != 'N' && buf[0] != 'n') continue; cp = index(buf, '\n'); if (cp) *cp = '\0'; cp = index(buf, ':'); if (cp == NULL) continue; *cp = '\0'; if (!strcasecmp(buf, "newsgroups")) { ngcount = get_nglist(&ngarray, cp+2); break; } } (void) rewind(fp); if (ngcount == 0) /* Either no newgroups or null entry */ return (1); return (ngmatch(s1strneql, ALLBUT, ngpermlist, ngpermcount, ngarray, ngcount)); } /* * spew -- spew out the contents of a file to stdout, doing * the necessary cr-lf additions at the end. Finish with * a "." on a line by itself, and an fflush(stdout). * * Parameters: "how" tells what part of the file we * want spewed: * ARTICLE The entire thing. * HEAD Just the first part. * BODY Just the second part. * "fp" is the open file to spew from. * * Returns: Nothing. * * Side effects: Changes current position in file. */ spew(fp, how) FILE *fp; int how; { char line[NNTP_STRLEN]; register char *cp; #ifdef LOG ++arts_acsd; #endif if (how == STAT) { (void) fflush(stdout); return; } while (fgets(line, sizeof(line)-6, fp) != NULL && *line != '\n') { if (how == BODY) /* We need to skip this anyway */ continue; cp = index(line, '\n'); if (cp != NULL) *cp = '\0'; if (*line == '.') putchar('.'); putline(line); if (cp == NULL) { for (;;) { if ((fgets(line, sizeof(line)-6, fp) == NULL) || (index(line, '\n') != NULL)) break; } } } if (how == HEAD) { putchar('.'); putchar('\r'); putchar('\n'); (void) fflush(stdout); return; } else if (how == ARTICLE) { putchar('\r'); putchar('\n'); } while (fgets(line, sizeof(line)-6, fp) != NULL) { cp = index(line, '\n'); if (cp != NULL) *cp = '\0'; if (*line == '.') putchar('.'); putline(line); if (cp == NULL) { for (;;) { if ((fgets(line, sizeof(line)-6, fp) == NULL) || (index(line, '\n') != NULL)) break; } } } putchar('.'); putchar('\r'); putchar('\n'); (void) fflush(stdout); } /* * get_id -- get the message id of the current article. * * Parameters: "art_fp" is a pointer to the open file. * "id" is space for the message ID. * * Returns: Nothing. * * Side effects: Seeks and rewinds on "art_fp". * Changes space pointed to by "id". */ get_id(art_fp, id) register FILE *art_fp; char *id; { char line[MAXBUFLEN]; register char *cp; while (fgets(line, sizeof(line), art_fp) != NULL) { if (*line == '\n') break; if (*line == 'M' || *line == 'm') { /* "Message-ID" */ if ((cp = index(line, ' ')) != NULL) { *cp = '\0'; if (!strcasecmp(line, "Message-ID:")) { (void) strcpy(id, cp + 1); if ((cp = index(id, '\n')) != NULL) *cp = '\0'; (void) rewind(art_fp); return; } } } } (void) rewind(art_fp); (void) strcpy(id, "<0>"); } /* * close_crnt -- close the current article file pointer, if it's * open. * * Parameters: None. * * Returns: Nothing. * * Side effects: Closes "art_fp" if it's open; sets "art_fp" to NULL. */ close_crnt() { if (art_fp != NULL) (void) fclose(art_fp); art_fp = NULL; } /* * findart -- find an article number in the article array. * * Parameters: "artname" is a string containing * the name of the article. * * Returns: An index into "art_array", * or -1 if "artname" isn't in "art_array". * * Side effects: None. * * Improvement: Replace this linear search with a binary one. */ findart(artname) char *artname; { register int i, artnum; artnum = atoi(artname); for (i = 0; i < num_arts; ++i) if (art_array[i] == artnum) return(i); return (-1); } /* * get_distlist -- return a nicely set up array of distribution groups * along with a count, when given an NNTP-spec distribution list * in the form . * * Parameters: "array" is storage for our array, * set to point at some static data. * "list" is the NNTP distribution list. * * Returns: Number of distributions found. * -1 on error. * * Side effects: Changes static data area. */ get_distlist(array, list) char ***array; char *list; { char *cp; int distcount; static char **dist_list = (char **) NULL; if (list[0] != '<') return (-1); cp = index(list + 1, '>'); if (cp != NULL) *cp = '\0'; else return (-1); for (cp = list + 1; *cp != '\0'; ++cp) if (*cp == ',') *cp = ' '; distcount = parsit(list + 1, &dist_list); *array = dist_list; return (distcount); } /* * lower -- convert a character to lower case, if it's upper case. * * Parameters: "c" is the character to be * converted. * * Returns: "c" if the character is not * upper case, otherwise the lower * case eqivalent of "c". * * Side effects: None. */ char lower(c) register char c; { if (isascii(c) && isupper(c)) c = c - 'A' + 'a'; return (c); } /* the following is from news 2.11 */ #ifdef USG /* ** Generate the appropriate history subfile name */ char * histfile(hline) char *hline; { char chr; /* least significant digit of article number */ static char subfile[BUFSIZ]; chr = findhfdigit(hline); sprintf(subfile, "%s.d/%c", HISTORY_FILE, chr); return subfile; } findhfdigit(fn) char *fn; { register char *p; register int chr; p = index(fn, '@'); if (p != NULL && p > fn) chr = *(p - 1); else chr = '0'; if (!isdigit(chr)) chr = '0'; return chr; } bcopy(s, d, l) register char *s, *d; register int l; { while (l-- > 0) *d++ = *s++; } bcmp(s1, s2, l) register char *s1, *s2; register int l; { if (l == 0) return (0); do if (*s1++ != *s2++) break; while (--l); return (l); } bzero(p, l) register char *p; register int l; { while (l-- > 0) *p++ = 0; } dup2(x,y) int x,y; { close(y); return(fcntl(x, F_DUPFD,y )); } #endif USG