⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 article.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  $Revision: 1.13 $****  Article-related routines.*/#include "nnrpd.h"/***  Data structures for use in ARTICLE/HEAD/BODY/STAT common code.*/typedef enum _SENDTYPE {    STarticle,    SThead,    STbody,    STstat} SENDTYPE;typedef struct _SENDDATA {    SENDTYPE	Type;    int		ReplyCode;    STRING	Item;} SENDDATA;/***  Information about the schema of the news overview files.*/typedef struct _ARTOVERFIELD {    char	*Header;    int		Length;    BOOL	HasHeader;} ARTOVERFIELD;STATIC char		ARTnotingroup[] = NNTP_NOTINGROUP;STATIC char		ARTnoartingroup[] = NNTP_NOARTINGRP;STATIC char		ARTnocurrart[] = NNTP_NOCURRART;STATIC QIOSTATE		*ARTqp;STATIC ARTOVERFIELD	*ARTfields;STATIC int		ARTfieldsize;STATIC SENDDATA		SENDbody = {    STbody,	NNTP_BODY_FOLLOWS_VAL,		"body"};STATIC SENDDATA		SENDarticle = {    STarticle,	NNTP_ARTICLE_FOLLOWS_VAL,	"article"};STATIC SENDDATA		SENDstat = {    STstat,	NNTP_NOTHING_FOLLOWS_VAL,	"status"};STATIC SENDDATA		SENDhead = {    SThead,	NNTP_HEAD_FOLLOWS_VAL,		"head"};/***  Overview state information.*/STATIC QIOSTATE		*OVERqp;		/* Open overview file	*/STATIC char		*OVERline;		/* Current line		*/STATIC ARTNUM		OVERarticle;		/* Current article	*/STATIC int		OVERopens;		/* Number of opens done	*//***  Read the overview schema.*/voidARTreadschema(){    static char			SCHEMA[] = _PATH_SCHEMA;    register FILE		*F;    register char		*p;    register ARTOVERFIELD	*fp;    register int		i;    char			buff[SMBUF];    /* Open file, count lines. */    if ((F = fopen(SCHEMA, "r")) == NULL)	return;    for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++)	continue;    (void)fseek(F, (OFFSET_T)0, SEEK_SET);    ARTfields = NEW(ARTOVERFIELD, i + 1);    /* Parse each field. */    for (fp = ARTfields; fgets(buff, sizeof buff, F) != NULL; ) {	/* Ignore blank and comment lines. */	if ((p = strchr(buff, '\n')) != NULL)	    *p = '\0';	if ((p = strchr(buff, COMMENT_CHAR)) != NULL)	    *p = '\0';	if (buff[0] == '\0')	    continue;	if ((p = strchr(buff, ':')) != NULL) {	    *p++ = '\0';	    fp->HasHeader = EQ(p, "full");	}	else	    fp->HasHeader = FALSE;	fp->Header = COPY(buff);	fp->Length = strlen(buff);	fp++;    }    ARTfieldsize = fp - ARTfields;    (void)fclose(F);}/***  If we have an article open, close it.*/voidARTclose(){    if (ARTqp) {	QIOclose(ARTqp);	ARTqp = NULL;    }}/***  Get the Message-ID from a file.*/STATIC voidARTgetmsgid(qp, id)    register QIOSTATE	*qp;    char		*id;{    register char	*p;    register char	*q;    for (*id = '\0'; (p = QIOread(qp)) != NULL && *p != '\0'; ) {	if (*p != 'M' && *p != 'm')	    continue;	if ((q = strchr(p, ' ')) == NULL)	    continue;	*q++ = '\0';	if (caseEQ(p, "Message-ID:")) {	    (void)strcpy(id, q);	    break;	}    }    (void)QIOrewind(qp);}/***  If the article name is valid, open it and stuff in the ID.*/STATIC BOOLARTopen(name, id)    char		*name;    char		*id;{    static ARTNUM	save_artnum;    static char		save_artid[BIG_BUFFER];    struct stat		Sb;    /* Re-use article if it's the same one. */    if (ARTqp != NULL) {	if (save_artnum == atol(name) && QIOrewind(ARTqp) != -1) {	    if (id)		(void)strcpy(id, save_artid);	    return TRUE;	}	QIOclose(ARTqp);    }    /* Open it, make sure it's a regular file. */    if ((ARTqp = QIOopen(name, QIO_BUFFER)) == NULL)	return FALSE;    if (fstat(QIOfileno(ARTqp), &Sb) < 0 || !S_ISREG(Sb.st_mode)) {	QIOclose(ARTqp);	ARTqp = NULL;	return FALSE;    }    CloseOnExec(QIOfileno(ARTqp), TRUE);    save_artnum = atol(name);    ARTgetmsgid(ARTqp, save_artid);    (void)strcpy(id, save_artid);    return TRUE;}/***  Open the article for a given Message-ID.*/STATIC QIOSTATE *ARTopenbyid(msg_id, ap)    char	*msg_id;    ARTNUM	*ap;{    QIOSTATE	*qp;    char	*p;    char	*q;    *ap = 0;    if ((p = HISgetent(msg_id, FALSE)) == NULL)	return NULL;    if ((qp = QIOopen(p, QIO_BUFFER)) == NULL)	return NULL;    CloseOnExec(QIOfileno(qp), TRUE);    if ((q = strrchr(p, '/')) != NULL)	*q++ = '\0';    if (GRPlast[0] && EQ(p, GRPlast))	*ap = atol(q);    return qp;}/***  Send a (part of) a file to stdout, doing newline and dot conversion.*/STATIC voidARTsend(qp, what)    register QIOSTATE	*qp;    SENDTYPE		what;{    register char	*p;    ARTcount++;    GRParticles++;    /* Get the headers. */    for ( ; ; ) {	p = QIOread(qp);	if (p == NULL) {	    if (QIOtoolong(qp))		continue;	    break;	}	if (*p == '\0')	    break;	if (what == STbody)	    continue;	Printf("%s%s\r\n", *p == '.' ? "." : "", p);    }    if (what == SThead) {	Printf(".\r\n");	return;    }    if (what == STarticle)	Printf("\r\n");    for ( ; ; ) {	p = QIOread(qp);	if (p == NULL) {	    if (QIOtoolong(qp))		continue;	    break;	}	Printf("%s%s\r\n", *p == '.' ? "." : "", p);    }    Printf(".\r\n");}/***  Find an article number in the article array via a binary search;**  return -1 if not found.  Cache last hit to make linear lookups**  faster.*/STATIC intARTfind(i)    register ARTNUM	i;{    register ARTNUM	*bottom;    register ARTNUM	*middle;    register ARTNUM	*top;    if (ARTsize == 0)	return -1;    top = &ARTnumbers[ARTsize - 1];    if (ARTcache && ++ARTcache <= top && *ARTcache <= i) {	if (*ARTcache == i)	    return ARTcache - ARTnumbers;	bottom = ARTcache;    }    else {	ARTcache = NULL;	bottom = ARTnumbers;    }    for ( ; ; ) {	if (i < *bottom || i > *top)	    break;	middle = bottom + (top - bottom) / 2;	if (i == *middle) {	    /* Found it; update cache. */	    ARTcache = middle;	    return middle - ARTnumbers;	}	if (i > *middle)	    bottom = middle + 1;	else	    top = middle;    }    return -1;}/***  Ask the innd server for the article.  Only called from CMDfetch,**  and only if history file is buffered.  Common case:  "oops, cancel**  that article I just posted."*/STATIC QIOSTATE *ARTfromboss(what, id)    SENDDATA		*what;    char		*id;{    FILE		*FromServer;    FILE		*ToServer;    QIOSTATE		*qp;    char		buff[NNTP_STRLEN + 2];    char		*name;    char		*p;    BOOL		more;    /* If we can, open the connection. */    if (NNTPlocalopen(&FromServer, &ToServer, (char *)NULL) < 0)	return NULL;    /* Send the query to the server. */    qp = NULL;    (void)fprintf(ToServer, "XPATH %s\r\n", id);    (void)fflush(ToServer);    if (ferror(ToServer))	goto QuitClose;    /* Get the reply; article exist? */    if (fgets(buff, sizeof buff, FromServer) == NULL     || atoi(buff) == NNTP_DONTHAVEIT_VAL)	goto QuitClose;    /* Yes.  Be quick if just doing a stat. */    if (what == &SENDstat) {	qp = QIOopen("/dev/null", 0);	goto QuitClose;    }    /* Clean up response. */    if ((p = strchr(buff, '\r')) != NULL)	*p = '\0';    if ((p = strchr(buff, '\n')) != NULL)	*p = '\0';    /* Loop over all filenames until we can open one. */    for (name = buff; *name; name = p + 1) {	/* Snip off next name, turn dots to slashes. */	for (p = name; ISWHITE(*p); p++)	    continue;	for (name = p; *p && *p != ' '; p++)	    if (*p == '.')		*p = '/';	more = *p == ' ';	if (more)	    *p = '\0';	if ((qp = QIOopen(name, QIO_BUFFER)) != NULL || !more)	    break;    }    /* Send quit, read server's reply, close up and return. */  QuitClose:    (void)fprintf(ToServer, "quit\r\n");    (void)fclose(ToServer);    (void)fgets(buff, sizeof buff, FromServer);    (void)fclose(FromServer);    return qp;}/***  Fetch part or all of an article and send it to the client.*/FUNCTYPECMDfetch(ac, av)    int			ac;    char		*av[];{    char		buff[SMBUF];    char		idbuff[BIG_BUFFER];    SENDDATA		*what;    register QIOSTATE	*qp;    register BOOL	ok;    ARTNUM		art;    /* Find what to send; get permissions. */    ok = PERMcanread;    switch (*av[0]) {    default:	what = &SENDbody;	break;    case 'a': case 'A':	what = &SENDarticle;	break;    case 's': case 'S':	what = &SENDstat;	break;    case 'h': case 'H':	what = &SENDhead;	/* Poster might do a "head" command to verify the article. */	ok = PERMcanread || PERMcanpost;	break;    }    if (!ok) {	Reply("%s\r\n", NOACCESS);	return;    }    /* Requesting by Message-ID? */    if (ac == 2 && av[1][0] == '<') {	if ((qp = ARTopenbyid(av[1], &art)) == NULL	 && (qp = ARTfromboss(what, av[1])) == NULL) {	    Reply("%d No such article\r\n", NNTP_DONTHAVEIT_VAL);	    return;	}	if (!PERMartok(qp)) {	    QIOclose(qp);	    Reply("%s\r\n", NOACCESS);	    return;	}	Reply("%d %ld %s %s\r\n", what->ReplyCode, art, what->Item, av[1]);	if (what->Type != STstat)	    ARTsend(qp, what->Type);	QIOclose(qp);	return;    }    /* Trying to read. */    if (GRPcount == 0) {	Reply("%s\r\n", ARTnotingroup);	return;    }    /* Default is to get current article, or specified article. */    if (ac == 1) {	if (ARTindex < 0 || ARTindex >= ARTsize) {	    Reply("%s\r\n", ARTnocurrart);	    return;	}	(void)sprintf(buff, "%ld", ARTnumbers[ARTindex]);    }    else {	if (strspn(av[1], "0123456789") != strlen(av[1])) {	    Reply("%s\r\n", ARTnoartingroup);	    return;	}	(void)strcpy(buff, av[1]);    }    /* Move forward until we can find one. */    while (!ARTopen(buff, idbuff)) {	if (ac > 1 || ++ARTindex >= ARTsize) {	    Reply("%s\r\n", ARTnoartingroup);	    return;	}	(void)sprintf(buff, "%ld", ARTnumbers[ARTindex]);    }    Reply("%d %s %s %s\r\n", what->ReplyCode, buff, idbuff, what->Item);    if (what->Type != STstat)	ARTsend(ARTqp, what->Type);    if (ac > 1)	ARTindex = ARTfind((ARTNUM)atol(buff));}/***  Go to the next or last (really previous) article in the group.*/FUNCTYPECMDnextlast(ac, av)    int		ac;    char	*av[];{    char	buff[SPOOLNAMEBUFF];    char	idbuff[SMBUF];    int		save;    BOOL	next;    int		delta;    int		errcode;    STRING	message;    if (!PERMcanread) {	Reply("%s\r\n", NOACCESS);	return;    }    if (GRPcount == 0) {	Reply("%s\r\n", ARTnotingroup);	return;    }    if (ARTindex < 0 || ARTindex >= ARTsize) {	Reply("%s\r\n", ARTnocurrart);	return;    }    next = (av[0][0] == 'n' || av[0][0] == 'N');    if (next) {	delta = 1;	errcode = NNTP_NONEXT_VAL;	message = "next";    }    else {	delta = -1;	errcode = NNTP_NOPREV_VAL;	message = "previous";    }    save = ARTindex;    ARTindex += delta;    if (ARTindex < 0 || ARTindex >= ARTsize) {	Reply("%d No %s to retrieve.\r\n", errcode, message);	ARTindex = save;	return;    }    (void)sprintf(buff, "%ld", ARTnumbers[ARTindex]);    while (!ARTopen(buff, idbuff)) {	ARTindex += delta;	if (ARTindex < 0 || ARTindex >= ARTsize) {	    Reply("%d No %s article to retrieve.\r\n", errcode, message);	    ARTindex = save;	    return;	}	(void)sprintf(buff, "%ld", ARTnumbers[ARTindex]);    }    Reply("%d %s %s Article retrieved; request text separately.\r\n",	   NNTP_NOTHING_FOLLOWS_VAL, buff, idbuff);    if (ac > 1)	ARTindex = ARTfind((ARTNUM)atol(buff));}/***  Return the header from the specified file, or NULL if not found.**  We can estimate the Lines header, if that's what's wanted.*/STATIC char *GetHeader(qp, header, IsLines)    register QIOSTATE	*qp;    register char	*header;    BOOL		IsLines;{    static char		buff[40];    register char	*p;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -