📄 article.c
字号:
register char *q; struct stat Sb; for ( ; ; ) { if ((p = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) continue; break; } if (*p == '\0') /* End of headers. */ break; if (ISWHITE(*p) || (q = strchr(p, ':')) == NULL) /* Continuation or bogus (shouldn't happen) line; ignore. */ continue; *q = '\0'; if (caseEQ(header, p)) return *++q ? q + 1 : NULL; } if (IsLines && fstat(QIOfileno(qp), &Sb) >= 0) { /* Lines estimation taken from Tor Lillqvist <tml@tik.vtt.fi>'s * posting <TML.92Jul10031233@hemuli.tik.vtt.fi> in * news.sysadmin. */ (void)sprintf(buff, "%d", (int)(6.4e-8 * Sb.st_size * Sb.st_size + 0.023 * Sb.st_size - 12)); return buff; } return NULL;}STATIC BOOLCMDgetrange(ac, av, rp) int ac; char *av[]; register ARTRANGE *rp;{ register char *p; if (GRPcount == 0) { Reply("%s\r\n", ARTnotingroup); return FALSE; } if (ac == 1) { /* No argument, do only current article. */ if (ARTindex < 0 || ARTindex >= ARTsize) { Reply("%s\r\n", ARTnocurrart); return FALSE; } rp->High = rp->Low = ARTnumbers[ARTindex]; return TRUE; } /* Got just a single number? */ if ((p = strchr(av[1], '-')) == NULL) { rp->Low = rp->High = atol(av[1]); return TRUE; } /* Parse range. */ *p++ = '\0'; rp->Low = atol(av[1]); if (ARTsize) { if (*p == '\0' || (rp->High = atol(p)) < rp->Low) /* "XHDR 234-0 header" gives everything to the end. */ rp->High = ARTnumbers[ARTsize - 1]; else if (rp->High > ARTnumbers[ARTsize - 1]) rp->High = ARTnumbers[ARTsize - 1]; if (rp->Low < ARTnumbers[0]) rp->Low = ARTnumbers[0]; } else /* No articles; make sure loops don't run. */ rp->High = rp->Low ? rp->Low - 1 : 0; return TRUE;}/*** Return a field from the overview line or NULL on error. Return a copy** since we might be re-using the line later.*/STATIC char *OVERGetHeader(p, field) register char *p; int field;{ static char *buff; static int buffsize; register int i; ARTOVERFIELD *fp; char *next; /* Skip leading headers. */ for (fp = &ARTfields[field - 1]; --field >= 0 && *p; p++) if ((p = strchr(p, '\t')) == NULL) return NULL; if (*p == '\0') return NULL; if (fp->HasHeader) p += fp->Length + 2; /* Figure out length; get space. */ if ((next = strchr(p, '\t')) != NULL) i = next - p; else i = strlen(p); if (buffsize == 0) { buffsize = i; buff = NEW(char, buffsize + 1); } else if (buffsize < i) { buffsize = i; RENEW(buff, char, buffsize + 1); } (void)strncpy(buff, p, i); buff[i] = '\0'; return buff;}/*** Open an OVERVIEW file.*/STATIC BOOLOVERopen(){ char name[SPOOLNAMEBUFF]; /* Already open? */ if (OVERqp != NULL) /* Don't rewind -- we are probably going forward via repeated * NNTP commands. */ return TRUE; /* Failed here before? */ if (OVERopens++) return FALSE; OVERline = NULL; OVERarticle = 0; (void)sprintf(name, "%s/%s/%s", _PATH_OVERVIEWDIR, GRPlast, _PATH_OVERVIEW); OVERqp = QIOopen(name, QIO_BUFFER); return OVERqp != NULL;}/*** Close the OVERVIEW file.*/voidOVERclose(){ if (OVERqp != NULL) { QIOclose(OVERqp); OVERqp = NULL; OVERopens = 0; }}/*** Return the overview data for an article or NULL on failure.** Assumes that what we return is never modified.*/STATIC char *OVERfind(artnum) ARTNUM artnum;{ if (OVERqp == NULL) return NULL; if (OVERarticle > artnum) { (void)QIOrewind(OVERqp); OVERarticle = 0; OVERline = NULL; } for ( ; OVERarticle < artnum; OVERarticle = atol(OVERline)) if ((OVERline = QIOread(OVERqp)) == NULL) { if (QIOtoolong(OVERqp)) continue; /* Don't close file; we may rewind. */ return NULL; } return OVERarticle == artnum ? OVERline : NULL;}/*** Read an article and create an overview line without the trailing** newline. Returns pointer to static space or NULL on error.*/STATIC char *OVERgen(name) char *name;{ static ARTOVERFIELD *Headers; static char *buff; static int buffsize; register ARTOVERFIELD *fp; register ARTOVERFIELD *hp; register QIOSTATE *qp; register char *colon; register char *line; register char *p; register int i; register int size; register int ov_size; register long lines; struct stat Sb; long t; char value[10]; /* Open article. */ if ((qp = QIOopen(name, QIO_BUFFER)) == NULL) return NULL; if ((p = strrchr(name, '/')) != NULL) name = p + 1; /* Set up place to store headers. */ if (Headers == NULL) { Headers = NEW(ARTOVERFIELD, ARTfieldsize); for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++) hp->Length = 0; } for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++) hp->HasHeader = FALSE; for ( ; ; ) { /* Read next line. */ if ((line = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) continue; /* Error or EOF (in headers!?); shouldn't happen. */ QIOclose(qp); return NULL; } /* End of headers? */ if (*line == '\0') break; /* See if we want this header. */ fp = ARTfields; for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++, fp++) { colon = &line[fp->Length]; if (*colon != ':') continue; *colon = '\0'; if (!caseEQ(line, fp->Header)) { *colon = ':'; continue; } *colon = ':'; if (fp->HasHeader) p = line; else /* Skip colon and whitespace, store value. */ for (p = colon; *++p && ISWHITE(*p); ) continue; size = strlen(p); if (hp->Length == 0) { hp->Length = size; hp->Header = NEW(char, hp->Length + 1); } else if (hp->Length < size) { hp->Length = size; RENEW(hp->Header, char, hp->Length + 1); } (void)strcpy(hp->Header, p); for (p = hp->Header; *p; p++) if (*p == '\t' || *p == '\n') *p = ' '; hp->HasHeader = TRUE; } } /* Read body of article, just to get lines. */ for (lines = 0; ; lines++) if ((p = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) continue; if (QIOerror(qp)) { QIOclose(qp); return NULL; } break; } /* Calculate total size, fix hardwired headers. */ ov_size = strlen(name) + ARTfieldsize + 2; for (hp = Headers, fp = ARTfields, i = ARTfieldsize; --i >= 0; hp++, fp++) { if (caseEQ(fp->Header, "Bytes") || caseEQ(fp->Header, "Lines")) { if (fp->Header[0] == 'B' || fp->Header[0] == 'b') t = fstat(QIOfileno(qp), &Sb) >= 0 ? (long)Sb.st_size : 0L; else t = lines; (void)sprintf(value, "%ld", t); size = strlen(value); if (hp->Length == 0) { hp->Length = size; hp->Header = NEW(char, hp->Length + 1); } else if (hp->Length < size) { hp->Length = size; RENEW(hp->Header, char, hp->Length + 1); } (void)strcpy(hp->Header, value); hp->HasHeader = TRUE; } if (hp->HasHeader) ov_size += strlen(hp->Header); } /* Get space. */ if (buffsize == 0) { buffsize = ov_size; buff = NEW(char, buffsize + 1); } else if (buffsize < ov_size) { buffsize = ov_size; RENEW(buff, char, buffsize + 1); } /* Glue all the fields together. */ p = buff + strlen(strcpy(buff, name)); for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++) { *p++ = '\t'; if (hp->HasHeader) p += strlen(strcpy(p, hp->Header)); } *p = '\0'; QIOclose(qp); return buff;}/*** XHDR, a common extension. Retrieve specified header from a** Message-ID or article range.*/FUNCTYPECMDxhdr(ac, av) int ac; char *av[];{ register QIOSTATE *qp; register ARTNUM i; register char *p; int Overview; BOOL IsLines; ARTRANGE range; char buff[SPOOLNAMEBUFF]; ARTNUM art; if (!PERMcanread) { Reply("%s\r\n", NOACCESS); return; } IsLines = caseEQ(av[1], "lines"); /* Message-ID specified? */ if (ac == 3 && av[2][0] == '<') { if ((qp = ARTopenbyid(av[2], &art)) == NULL) { Reply("%d No such article\r\n", NNTP_DONTHAVEIT_VAL); return; } Reply("%d %ld %s header of article %s.\r\n", NNTP_HEAD_FOLLOWS_VAL, art, av[1], av[2]); p = GetHeader(qp, av[1], IsLines); Printf("%s %s\r\n", av[2], p ? p : "(none)"); QIOclose(qp); Printf(".\r\n"); return; } /* Range specified. */ if (!CMDgetrange(ac - 1, av + 1, &range)) return; /* Is this a header in our overview? */ for (Overview = 0, i = 0; i < ARTfieldsize; i++) if (caseEQ(ARTfields[i].Header, av[1])) { if (OVERopen()) Overview = i + 1; break; } Reply("%d %s fields follow\r\n", NNTP_HEAD_FOLLOWS_VAL, av[1]); for (i = range.Low; i <= range.High; i++) { if (ARTfind(i) < 0) continue; /* Get it from the overview? */ if (Overview && (p = OVERfind(i)) != NULL) { p = OVERGetHeader(p, Overview); Printf("%d %s\r\n", i, p && *p ? p : "(none)"); continue; } (void)sprintf(buff, "%ld", i); if ((qp = QIOopen(buff, QIO_BUFFER)) == NULL) continue; p = GetHeader(qp, av[1], IsLines); Printf("%d %s\r\n", i, p ? p : "(none)"); QIOclose(qp); } Printf(".\r\n");}/*** XOVER another extension. Dump parts of the overview database.*/FUNCTYPECMDxover(ac, av) int ac; char *av[];{ register char *p; register ARTNUM i; register BOOL Opened; ARTRANGE range; char buff[SPOOLNAMEBUFF]; if (!PERMcanread) { Printf("%s\r\n", NOACCESS); return; } /* Trying to read. */ if (GRPcount == 0) { Reply("%s\r\n", ARTnotingroup); return; } /* Parse range. */ if (!CMDgetrange(ac, av, &range)) return; Reply("%d data follows\r\n", NNTP_OVERVIEW_FOLLOWS_VAL); for (Opened = OVERopen(), i = range.Low; i <= range.High; i++) { if (ARTfind(i) < 0) continue; if (Opened && (p = OVERfind(i)) != NULL) { Printf("%s\r\n", p); continue; } (void)sprintf(buff, "%ld", i); if ((p = OVERgen(buff)) != NULL) Printf("%s\r\n", p); } Printf(".\r\n");}/*** XPAT, an uncommon extension. Print only headers that match the pattern.*//* ARGSUSED */FUNCTYPECMDxpat(ac, av) int ac; char *av[];{ register char *p; register QIOSTATE *qp; register ARTNUM i; ARTRANGE range; char *header; char *pattern; char *text; int Overview; char buff[SPOOLNAMEBUFF]; ARTNUM art; if (!PERMcanread) { Printf("%s\r\n", NOACCESS); return; } header = av[1]; /* Message-ID specified? */ if (av[2][0] == '<') { p = av[2]; qp = ARTopenbyid(p, &art); if (qp == NULL) { Printf("%d No such article.\r\n", NNTP_DONTHAVEIT_VAL); return; } Printf("%d %s matches follow.\r\n", NNTP_HEAD_FOLLOWS_VAL, header); pattern = Glom(&av[3]); if ((text = GetHeader(qp, header, FALSE)) != NULL && wildmat(text, pattern)) Printf("%s %s\r\n", p, text); QIOclose(qp); Printf(".\r\n"); DISPOSE(pattern); return; } /* Range specified. */ if (!CMDgetrange(ac - 1, av + 1, &range)) return; /* In overview? */ for (Overview = 0, i = 0; i < ARTfieldsize; i++) if (caseEQ(ARTfields[i].Header, av[1])) { if (OVERopen()) Overview = i + 1; break; } Printf("%d %s matches follow.\r\n", NNTP_HEAD_FOLLOWS_VAL, header); for (pattern = Glom(&av[3]), i = range.Low; i < range.High; i++) { if (ARTfind(i) < 0) continue; /* Get it from the Overview? */ if (Overview && (p = OVERfind(i)) != NULL && (p = OVERGetHeader(p, Overview)) != NULL) { if (wildmat(p, pattern)) Printf("%ld %s\r\n", i, p); continue; } (void)sprintf(buff, "%ld", i); if ((qp = QIOopen(buff, QIO_BUFFER)) == NULL) continue; if ((p = GetHeader(qp, av[1], FALSE)) == NULL) p = "(none)"; if (wildmat(p, pattern)) Printf("%ld %s\r\n", i, p); QIOclose(qp); } Printf(".\r\n"); DISPOSE(pattern);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -