home *** CD-ROM | disk | FTP | other *** search
- /*
- **
- ** This software is Copyright (c) 1989 by Kent Landfield.
- **
- ** Permission is hereby granted to copy, distribute or otherwise
- ** use any part of this package as long as you do not try to make
- ** money from it or pretend that you wrote it. This copyright
- ** notice must be maintained in any copy made.
- **
- ** History:
- ** Creation: Tue Feb 21 08:52:35 CST 1989 due to necessity.
- **
- */
- #ifndef lint
- static char SID[] = "@(#)header.c 1.1 6/1/89";
- #endif
-
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include "article.h"
-
- int its(s1)
- register char *s1;
- {
- if (strncmp(s,s1,strlen(s1)) == 0)
- return(TRUE);
- return(FALSE);
- }
-
- int line_type()
- {
- if (its("Path: "))
- return PATH;
- if (its("From: "))
- return FROM;
- if (its("Newsgroups: "))
- return NEWSGROUP;
- if (its("Subject: "))
- return SUBJECT;
- if (its("Keywords: "))
- return KEYWORDS;
- if (its("Date: "))
- return DATE;
- if (its("Message-ID: "))
- return MSG_ID;
- if (its("Lines: "))
- return NUMLINES;
- if (its("Approved: "))
- return APPROVED;
-
- /* The following is the auxilliary headers used by */
- /* the moderators of the sources groups. In some */
- /* cases, line checks are done with "historical" */
- /* auxilliary headers. Most of the moderators have */
- /* now standardized on comp.sources.unix's format.*/
-
- /* Archive header lines for comp.sources.unix */
- /* for comp.sources.amiga, comp.sources.atari.st, */
- /* comp.sources.misc, and comp.sources.x. */
-
- if (its("Submitted-by: "))
- return SUBMITTED_BY;
- if (its("Posting-number: "))
- return POSTING_NUMBER;
- if (its("Archive-name: "))
- return ARCH_NAME;
-
- /* Archive header lines for historical purposes */
- /* once used in comp.sources.misc */
-
- if (its("Submitted-By: "))
- return SUBMITTED_BY;
- if (its("comp.sources.misc: "))
- return POSTING_NUMBER;
- if (its("Archive-Name: "))
- return ARCH_NAME;
-
- /* Archive header lines used in comp.sources.games */
- /* Archive-name is the same as comp.sources.unix */
-
- if (its("Submitted by: "))
- return SUBMITTED_BY;
- if (its("Comp.sources.games: "))
- return POSTING_NUMBER;
-
- /* Auxiliary header used as a backward reference */
- /* to the location of the initially posted sources */
- /* in the event of a patch. This line only exists */
- /* if the current article is a patch. */
-
- if (its("Patch-To: "))
- return PATCH_TO;
-
- /* Archive header lines for historical purposes */
- /* once used in mod.sources articles. */
-
- if (its("Mod.sources: "))
- return POSTING_NUMBER;
-
- /* The remainder are other types of lines included */
- /* headers and are includes for formatting output */
- /* and for potential future use. */
-
- if (its("References: "))
- return REFERENCES;
- if (its("Organization: "))
- return ORGANIZATION;
- if (its("Distribution: "))
- return DISTRIBUTION;
- if (its("Xref: "))
- return XREF;
- if (its("Expires: "))
- return EXPIRE;
- if (its("Article-I.D.: "))
- return ARTICLEID;
- if (its("Reply-To: "))
- return REPLY_TO;
- if (its("Control: "))
- return CONTROL;
- if (its("Sender: "))
- return SENDER;
- if (its("Followup-To: "))
- return FOLLOWUP_TO;
- if (its("Summary: "))
- return SUMMARY;
- if (its("Supersedes: "))
- return SUPERSEDES;
-
- return OTHER;
- }
-
- data(hpfield, size, fldname)
- char *hpfield;
- int size;
- char *fldname;
- {
- register char *ptr;
- register char *p;
- char *strncpy();
- char *strchr();
-
- for (ptr = strchr(s, ':'); isspace(*++ptr); )
- ;
- if (*ptr != '\0') {
- (void) strncpy(hpfield, ptr, size - 1);
- /*
- * Strip trailing newlines, blanks, and tabs from hpfield.
- */
- for (p = hpfield; *p; ++p)
- ;
- while (--p >= hpfield && (*p == '\n' || *p == ' ' || *p == '\t'))
- ;
- *++p = '\0';
- }
- if (debug)
- (void) fprintf(logfp,"%s: %s\n",fldname, hpfield);
- }
-
- dump_article()
- {
- char *type_str;
-
- switch(article.rectype) {
- case PATCH : type_str = "PATCH";
- break;
- case INFORMATIONAL : type_str = "INFORMATIONAL";
- break;
- default : type_str = "NORMAL";
- break;
- }
-
- (void) fprintf(logfp,"Article: [%s]\n",article.newsarticle);
- (void) fprintf(logfp," newsgroup: [%s]\n",article.newsgroup);
- (void) fprintf(logfp," filename: [%s]\n",article.filename);
- (void) fprintf(logfp," volume: [%d]\n",article.volume);
- (void) fprintf(logfp," issue: [%d]\n",article.issue);
- (void) fprintf(logfp," record type: [%s]\n", type_str);
- if (article.rectype == PATCH) {
- (void) fprintf(logfp," patch volume: [%d]\n",article.patch_volume);
- (void) fprintf(logfp," patch issue: [%d]\n",article.patch_issue);
- }
- (void) fprintf(logfp," reposted: [%s]\n",
- article.repost ? "YES": "NO");
- (void) fprintf(logfp," description: [%s]\n",article.description);
- (void) fprintf(logfp," author's name: [%s]\n",article.author_name);
- (void) fprintf(logfp," author's logon: [%s]\n\n",article.author_signon);
- }
-
- init_article()
- {
- article.newsgroup[0] = '\0';
- article.newsarticle[0] = '\0';
- article.filename[0] = '\0';
- article.volume = -1;
- article.issue = -1;
- article.rectype = NORMAL;
- article.repost = FALSE;
- article.patch_volume = -1;
- article.patch_issue = -1;
- article.description[0] = '\0';
- article.author_name[0] = '\0';
- article.author_signon[0] = '\0';
-
- header.from[0] = '\0'; /* From: */
- header.path[0] = '\0'; /* Path: */
- header.nbuf[0] = '\0'; /* Newsgroups: */
- header.subject[0] = '\0'; /* Subject: */
- header.ident[0] = '\0'; /* Message-ID: */
- header.replyto[0] = '\0'; /* Reply-To: */
- header.references[0] = '\0'; /* References: */
- header.subdate[0] = '\0'; /* Date: (submission) */
- header.subtime = 0; /* subdate in secs */
- header.expdate[0] = '\0'; /* Expires: */
- header.ctlmsg[0] = '\0'; /* Control: */
- header.sender[0] = '\0'; /* Sender: */
- header.followup_to[0] = '\0'; /* Followup-to: */
- header.distribution[0] = '\0'; /* Distribution: */
- header.organization[0] = '\0'; /* Organization: */
- header.numlines[0] = '\0'; /* Lines: */
- header.intnumlines = 0; /* Integer Version */
- header.keywords[0] = '\0'; /* Keywords: */
- header.summary[0] = '\0'; /* Summary: */
- header.approved[0] = '\0'; /* Approved: */
- header.xref[0] = '\0'; /* Xref: */
- header.supersedes[0] = '\0'; /* Supersedes: */
- header.submitted_by[0] = '\0'; /* Submitted_by: */
- header.posting_num[0] = '\0'; /* Posting-number: */
- header.archive_name[0] = '\0'; /* Archive-name: */
- header.patch_to[0] = '\0'; /* Patch-To: */
- }
-
- store_line()
- {
- char *strchr(), *strcpy(), *strstrip(), *substr();
- char *dp, *sp;
- char wrk[20];
-
- switch(line_type()) {
-
- case PATH: /*PATH REQUIRED************************/
- data(header.path, sizeof(header.path), "PATH:");
- break;
-
- case FROM: /*FROM REQUIRED************************/
- data(header.from, sizeof(header.from), "FROM:");
- break;
-
- case NEWSGROUP: /*NEWSGROUP REQUIRED**************/
- data(header.nbuf, sizeof(header.nbuf), "NEWSGROUPS:");
- if ((sp = strchr(s,':')) != NULL) {
- do {
- ++sp;
- } while(!isalpha(*sp));
- /* remove all crossposting labels */
- if ((dp = strchr(sp,',')) != NULL)
- *dp = '\0';
- (void) strcpy(article.newsgroup,sp);
- }
- break;
-
- case SUBJECT: /*SUBJECT REQUIRED******************/
- data(header.subject, sizeof(header.subject), "SUBJECT:");
- /*
- ** Save the subject as the description for articles
- ** that have no volume/issue format. Later in the
- ** code, this subject line minus the volume/issue
- ** is stored back in the .description element if
- ** the volume/issue indicator is found.
- */
- (void) strcpy(article.description, header.subject);
-
- /*
- ** Check to see if this article is a repost of
- ** a previously posted article.
- */
- if (substr(s, "REPOST") != NULL)
- article.repost = TRUE;
-
- /*
- ** Time to get the filename. Assure that it is in a
- ** volume/issue (v01INF1 or v01i001) format.
- */
- if ((sp = strchr(s,'v')) == NULL)
- return; /* no volume indicator */
-
- /*
- ** Is there a number that follows
- ** the volume indicator ?
- */
- if (*(sp+1) < '0' || *(sp+1) > '9')
- return; /* The volume number is missing */
-
- /*
- ** Is there a second ':' as well ?
- */
- (void) strcpy(article.filename,sp);
- if ((dp = strchr(article.filename,':')) == NULL)
- return; /* not in v01i001: format */
-
- /*
- ** terminate the article's filename and
- ** store the article's description
- */
- *dp = '\0';
- (void) strcpy(article.description, strstrip(++dp));
-
- /*
- ** Store the filename in a work
- ** buffer so I can stomp on it.
- */
- (void) strcpy(wrk, article.filename);
-
- /*
- ** This is an informational posting.
- */
- if ((dp = substr(wrk, "INF")) != NULL) {
- article.rectype = INFORMATIONAL;
- article.issue = atoi((dp+3));
- ++sp;
- *dp = '\0';
- article.volume = atoi(sp);
- }
-
- /*
- ** check to see if there is an issue indicator
- */
- else if ((dp = strchr(++sp,'i')) == NULL)
- return; /* proven guilty. not volume/issue format */
-
- /* parse the volume from the filename */
- *dp = '\0';
- article.volume = atoi(sp);
-
- /* parse the issue from the filename */
- sp = ++dp;
- while (isdigit(*dp)) ++dp;
- *dp = '\0';
- article.issue = atoi(sp);
-
- break;
-
- case DATE:
- data(header.subdate, sizeof(header.subdate), "DATE:");
- break;
-
- case EXPIRE:
- data(header.expdate, sizeof(header.expdate), "EXPIRES:");
- break;
-
- case MSG_ID:
- data(header.ident, sizeof(header.ident), "MESSAGE-ID:");
- break;
-
- case REPLY_TO:
- data(header.replyto, sizeof(header.replyto), "REPLY-TO:");
- break;
-
- case REFERENCES:
- data(header.references, sizeof(header.references), "REFERENCES:");
- break;
-
- case SENDER:
- data(header.sender, sizeof(header.sender), "SENDER:");
- break;
-
- case FOLLOWUP_TO:
- data(header.followup_to, sizeof(header.followup_to),"FOLLOWUP-TO:");
- break;
-
- case CONTROL:
- data(header.ctlmsg, sizeof(header.ctlmsg),"CONTROL:");
- break;
-
- case DISTRIBUTION:
- data(header.distribution, sizeof(header.distribution),"DISTRIBUTION:");
- break;
-
- case ORGANIZATION:
- data(header.organization, sizeof(header.organization),"ORGANIZATION:");
- break;
-
- case NUMLINES:
- data(header.numlines, sizeof(header.numlines),"LINES:");
- header.intnumlines = atoi(header.numlines);
- break;
-
- case KEYWORDS:
- data(header.keywords, sizeof(header.keywords), "KEYWORDS:");
- break;
-
- case APPROVED:
- data(header.approved, sizeof(header.approved), "APPROVED:");
- break;
-
- case SUPERSEDES:
- data(header.supersedes, sizeof(header.supersedes),"SUPERSEDES:");
- break;
-
- case XREF:
- data(header.xref, sizeof(header.xref),"XREF:");
- break;
-
- case SUMMARY:
- data(header.summary, sizeof(header.summary),"SUMMARY:");
- break;
-
- case POSTING_NUMBER:
- data(header.posting_num, sizeof(header.posting_num), "POSTING_NUMBER:");
- break;
-
- case SUBMITTED_BY:
- data(header.submitted_by, sizeof(header.submitted_by), "SUBMITTED_BY:");
- /*
- ** Save the author's name and sign on if specified
- ** Can be in any of the following formats:
- ** kent@ssbell.uucp
- ** kent@ssbell.uucp (Kent Landfield)
- ** Kent Landfield <kent@ssbell.uucp>
- */
- if ((sp = strchr(s,':')) != NULL) {
- (void) strcpy(article.author_signon,(sp+2));
- /*
- ** Has a name been attached to the signon ?
- */
- if ((dp = strchr(article.author_signon,'<')) != NULL) {
- *(dp-1) = '\0';
- (void) strcpy(article.author_name, article.author_signon);
- (void) strcpy(article.author_signon, ++dp);
- /*
- ** Save the name, removing the <>.
- */
- if ((dp = strchr(article.author_signon,'>')) != NULL)
- *dp = '\0';
- }
- else if ((dp = strchr(article.author_signon,'(')) != NULL) {
- *(dp-1) = '\0';
- /*
- ** Save the name, removing the ().
- */
- (void) strcpy(article.author_name, ++dp);
- if ((dp = strchr(article.author_name,')')) != NULL)
- *dp = '\0';
- }
- }
- break;
-
- case ARCH_NAME:
- data(header.archive_name,sizeof(header.archive_name),"ARCH_NAME:");
- break;
-
- case PATCH_TO:
- data(header.patch_to,sizeof(header.patch_to),"PATCH_TO:");
- article.rectype = PATCH; /* set the article type */
-
- /*
- ** Parse the initially posted article's volume and issue.
- ** The format of the auxiliary header is
- **
- ** Patch-To: Volume 5, Issue 110
- **
- ** In the case of multipart initial postings, the Patch-To:
- ** line points to the first issue.
- */
-
- /*
- ** First get the volume number.
- */
-
- dp = s;
- while (*dp && (!isdigit(*dp)))
- ++dp;
- sp = dp;
- while (*dp && (isdigit(*dp)))
- ++dp;
- *dp = '\0';
- article.patch_volume = atoi(sp);
-
- /*
- ** Now get the issue number.
- */
-
- ++dp;
- while (*dp && (!isdigit(*dp)))
- ++dp;
- sp = dp;
- while (*dp && (isdigit(*dp)))
- ++dp;
- *dp = '\0';
- article.patch_issue = atoi(sp);
- break;
- }
- return;
- }
-