Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!shadooby!samsung!munnari.oz.au!basser!ultima!nick From: nick@ultima.cs.uts.oz (Nick Andrew) Newsgroups: comp.os.minix Subject: News for Minix (part 4 of 12) Keywords: news Message-ID: <16746@ultima.cs.uts.oz> Date: 7 Dec 89 11:51:59 GMT Organization: Comp Sci, NSWIT, Australia Lines: 1596 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'postnews.c' <<'END_OF_FILE' X/* X * This software is Copyright (c) 1986 by Rick Adams. X * X * Permission is hereby granted to copy, reproduce, redistribute or X * otherwise use this software as long as: there is no monetary X * profit gained specifically from the use or reproduction or this X * software, it is not sold, rented, traded or otherwise marketed, and X * this copyright notice is included prominently in any copy X * made. X * X * The author make no claims as to the fitness or correctness of X * this software for any use whatsoever, and it is provided as is. X * Any use of this software is at the user's own risk. X * X * Postnews: post a news message to Usenet. This C version replaces a shell X * script, and does more intelligent prompting and filtering than possible X * in a shell script. X */ X#ifdef SCCSID Xstatic char *SccsId = "@(#)postnews.c 1.31 3/21/87"; X#endif /* SCCSID */ X X#include "params.h" X X#define APPEND 1 X#define REPLACE 2 X Xextern char *MAILPARSER; X Xchar tempfname[50]; /* file name used for making article */ Xchar original[BUFLEN]; /* file name of original, used in followup */ Xchar homedir[BUFLEN]; /* HOME environment setting */ Xchar user[SBUFLEN]; /* user name */ Xchar ccname[BUFLEN]; /* file name for article copy */ X X/* article header information */ Xchar subject[BUFLEN]; Xchar distribution[BUFLEN]; Xchar references[BUFLEN]; Xchar newsgroups[BUFLEN]; Xchar isfrom[BUFLEN]; Xchar msgid[BUFLEN]; Xchar keywords[BUFLEN]; Xchar summary[BUFLEN]; X Xchar ngsep[] = { NGDELIM, '\0' }; /* == "," */ X Xchar *Progname = "postnews"; /* for xerror */ X Xtime_t fmodtime; Xchar pobuf[BUFLEN]; X X#define MAXDISTR 16 Xstruct distr { X char abbr[24]; X char descr[128]; X} distr[MAXDISTR]; X Xchar def_distr[24] = ""; /* default distribution */ XFILE *xfopen(); X Xmain(argc, argv) Xchar *argv[]; X{ X register int c; X X init(); X X if (argc == 2) { X if (!prefix(argv[1], SPOOL)) X xerror("Can only followup to articles in %s", SPOOL); X followup(argv[1]); X (void) strcpy(original, argv[1]); X } else X if (askyes("Is this message in response to some other message? ","no")) { X char ng[BUFLEN], num[BUFLEN]; X long i, j, lastnum; X register char *p; X int fd, dir; X char canpost; X X getpr("In what newsgroup was the article posted? ",ng); X if (!valid_ng(ng, &i, &j, &canpost)) X if (canpost == 'i' ) X byebye("There is no such newsgroup."); X else if (canpost == 'n') X byebye("You are not allowed to post to that group."); X X printf("Valid article numbers are from %ld to %ld\n", j, i); X lastnum = i + 1; X dir = -1; X X for(;;) { X getpr("\nWhat was the article number? ", num); X switch(num[0]) { X case '+': X dir = 1; X sprintf(num, "%ld", lastnum + 1); X break; X case '-': X dir = -1; X /* no break */ X case '\0': X sprintf(num, "%ld", lastnum + dir); X break; X } X (void) sprintf(original, "%s/%s", SPOOL, ng); X for (p=original+strlen(SPOOL)+1; *p ;++p) X if (*p == '.') X *p = '/'; X (void) strcat(original, "/"); X (void) strcat(original, num); X X if ((fd=open(original,0)) >= 0) { X (void) close(fd); X printf("\narticle %s\n", original); X if (article_line(original, "From: ", pobuf)) X printf("%s\n", pobuf); X if (article_line(original, "Subject: ", pobuf)) X printf("%s\n", pobuf); X if (askyes("Is this the one you want? ", "n")) X break; X } else X printf("I can't find that article.\n"); X lastnum = atol(num); X } X X followup(original); X } else { X do { X getpr("Subject: ", subject); X if (*subject == '?') { Xprintf("People read the subject line to learn what your article is about.\n"); Xprintf("You want it to do the same job as a newspaper headline.\n"); Xprintf("So type in something both brief and descriptive.\n"); X *subject = '\0'; X } X } while (*subject == '\0'); X getpr("Keywords: ", keywords); X X while (!get_newsgroup()) X ; X get_distribution((char *)0); X } X X if (pre_checks()) X exit(1); X X prep_article(); X c = 'e'; X for (;;) { X if (c == 'e') { X edit_article(); X post_checks(); X } X do { X do { X getpr("\nWhat now? [send, edit, list, quit, write, append] ", pobuf); X c = pobuf[0]; X } while (c == '\0'); X if (isupper(c)) X c = tolower(c); X if (c == 'q') { X (void) UNLINK(tempfname); X exit(1); X } X if (c == 'l') { X char *pager = getenv("PAGER"); X char lbuf[BUFLEN]; X if (pager == NULL || *pager == '\0') { X#ifdef PAGE X# ifdef IHCC X (void) sprintf(lbuf,"%s/bin/%s", logdir(HOME), PAGE); X# else /* !IHCC */ X (void) strcpy(lbuf, PAGE); X# endif /* !IHCC */ X pager = lbuf; X#else /* !PAGE */ X pager = "cat"; X#endif /* !PAGE */ X } X sprintf(pobuf, "exec %s %s", pager, tempfname); X (void) system(pobuf); X } X if (c == 'w' || c == 'a') { X register int ifd, ofd, nbytes; X char iobuf[BUFSIZ]; X char fname[BUFLEN]; X getpr("Filename? ", fname); X if (fname[0] == '\0') X continue; X ofd = (c == 'w') ? creat(fname, 0666) X : open(fname, 2); X if (ofd < 0) X perror(fname); X else { X if (c == 'a') X (void) lseek(ofd, 0L, 2); X ifd = open(tempfname, 0); X if (ifd < 0) X xerror("Can't reopen %s\n", tempfname); X while ((nbytes = read(ifd, iobuf, BUFSIZ)) > 0 ) X write(ofd, iobuf, nbytes); X close(ofd); X close(ifd); X } X } X } while (!index("eps", c)); X if (c != 'e') X post_article(); /* will exit if posted successfully */ X }; X} X X/* X * Find out the topic of interest. X */ Xget_newsgroup() X{ X int n; X long i; X char canpost; X static int first = 1; X X printf("Newsgroups (enter one at a time, end with a blank line):\n"); X if (first) { X printf("\nThe most relevant newsgroup should be the first, you should\n"); X printf("add others only if your article really MUST be read by people\n"); X printf("who choose not to read the appropriate group for your article.\n"); X printf("But DO use multiple newsgroups rather than posting many times.\n\n"); X first = 0; X } X printf("For a list of newsgroups, type ?\n"); X n = 0; X newsgroups[0] = '\0'; X X for(;;) { X getpr("> ", pobuf); X if (pobuf[0] == '\0') X if (n == 0) X return FALSE; X else X return TRUE; X if (pobuf[0] == '?'){ X char *pager = getenv("PAGER"); X char lbuf[BUFLEN]; X if (pager == NULL) { X#ifdef PAGE X# ifdef IHCC X (void) sprintf(lbuf,"%s/bin/%s", logdir(HOME), PAGE); X# else /* !IHCC */ X (void) strcpy(lbuf, PAGE); X# endif /* !IHCC */ X pager = lbuf; X#else /* !PAGE */ X pager = "cat"; X#endif /* !PAGE */ X } X printf("These are the currently active groups:\n"); X (void) fflush(stdout); X sprintf(pobuf, "exec %s %s/newsgroups", pager, LIB); X (void) system(pobuf); X continue; X } X if (valid_ng(pobuf, &i, &i, &canpost)) { X if (n++ != 0) X (void) strcat(newsgroups, ngsep); X (void) strcat(newsgroups, pobuf); X } else { X if (canpost == 'n') X printf("You are not allowed to post to %s\n", X pobuf); X else if (canpost == 'i') X printf("%s is not a valid newsgroup.\n", pobuf); X } X } X} X X/* X * Find out how widely the author wants the message distributed. X */ Xget_distribution(deflt) X char *deflt; X{ X register int i; X register char *r; X char def[BUFLEN]; X char *lastgroup; X X lastgroup = newsgroups; X (void) strcpy(def, newsgroups); X r = index(def, NGDELIM); X if (r) X *r = '\0'; X r = index(def, '.'); X if (r) { X *r = '\0'; X if (strcmp(def, "net") == 0) X (void) strcpy(def, "world"); X } else { X distribution[0] = '\0'; X return; X } X X if (strcmp(def, "to") == 0) { X /* X * This only works if "to.xx" is the first (or only) X * newsgroup, but it usually is .. X * Perhaps we should make the distribution be "to.xxx" ?? X */ X distribution[0] = '\0'; X return; /* He's probably testing something */ X } X if (deflt != (char *)0) X (void) strcpy(def, deflt); X if (ngmatch("misc.test", newsgroups)) X (void) strcpy(def, "local"); X for (i=0; distr[i].abbr[0]; i++) { X if (strcmp(distr[i].abbr, def) == 0) X break; X } X if (distr[i].abbr[0] == '\0') X strcpy(def, def_distr); X for(;;) { X do { X (void) sprintf(pobuf, "Distribution (default='%s', '?' for help) : ", def); X getpr(pobuf, distribution); X if (distribution[0] == '\0') { X if (strcmp(def, "*None*") == 0) X printf("You must enter a distribution, '?' for help.\n"); X (void) strcpy(distribution, def); X } X } while (strcmp(distribution, "*None*") == 0); X X /* Did the user ask for help? */ X if (distribution[0] == '?') { X printf("How widely should your article be distributed?\n\n"); X for (i=0; distr[i].abbr[0]; i++) X printf("%s\t%s\n", distr[i].abbr, distr[i].descr); X printf("\nEnter the word that specifies the distribution that you require.\n"); X continue; X } X X /* Check that it's a proper distribution */ X for (i=0; distr[i].abbr[0]; i++) { X if (strncmp(distr[i].abbr, distribution, sizeof(distr[0].abbr)) == 0) { X return; X } X } X if (strcmp(distribution, def) != 0) X printf("Type ? for help.\n"); X else { X int once = TRUE; X X do { X r = lastgroup; X while (r = index(r, NGDELIM)) X if (!prefix(++r, def)) X break; X if (r == NULL) { X /* X * no newsgroups are distribution X * names, and user simply will X * not type a valid distribution, X * assume that the default is OK. X */ X distribution[0] = '\0'; X return; X } X lastgroup = r; X if (once) X printf("Sorry, '%s' is an unknown distribution. Type ? for help.\n", def); X once = FALSE; X strcpy(def, r); X r = index(def, NGDELIM); X if (r) X *r = '\0'; X r = index(def, '.'); X } while (r == NULL); X *r = '\0'; X if (strcmp(def, "net") == 0) X strcpy(def, "world"); X } X } X} X X/* X * Do sanity checks before the author types in the message. X */ Xpre_checks() X{ X if (recording(newsgroups)) X return 1; X return 0; X} X X/* X * Set up the temp file with headers. X */ Xprep_article() X{ X FILE *tf, *of; X struct stat stbuf; X X (void) strcpy(tempfname, "/tmp/postXXXXXX"); X (void) mktemp(tempfname); X X /* insert a header */ X tf = xfopen(tempfname, "w"); X fprintf(tf, "Subject: %s\n", subject); X fprintf(tf, "Newsgroups: %s\n", newsgroups); X if (distribution[0] != '\0' && strcmp(distribution, "world")) X fprintf(tf, "Distribution: %s\n", distribution); X X if (keywords[0] != '\0') X fprintf(tf, "Keywords: %s\n", keywords); X if (summary[0] != '\0') X fprintf(tf, "Summary: %s\n", summary); X X if (references[0] != '\0') { X fprintf(tf, "References: %s\n\n", references); X X if (askyes("Do you want to include a copy of the article? ", "no")){ X of = xfopen(original, "r"); X while (fgets(pobuf, BUFSIZ, of) != NULL) X if (pobuf[0] == '\n') /* skip headers */ X break; X fprintf(tf, "In article %s, %s writes:\n", msgid, isfrom); X while (fgets(pobuf, BUFSIZ, of) != NULL) X fprintf(tf, "> %s", pobuf); X (void) fclose(of); X printf("OK, but please edit it to suppress unnecessary verbiage, signatures, etc.\n"); X (void) fflush(stdout); X } X } X X fprintf(tf, "\n\n"); X (void) fflush(tf); X (void) fstat(fileno(tf), &stbuf); X fmodtime = stbuf.st_mtime; X (void) fclose(tf); X} X Xedit_article() X{ X register char *p; X char *editor; X char *endflag = ""; X char *getenv(); X X /* edit the file */ X editor = getenv("EDITOR"); X if (editor == NULL) X editor = DFTEDITOR; X X p = editor + strlen(editor) - 2; X if (strcmp(p, "vi") == 0) X endflag = "+"; X X (void) sprintf(pobuf, "A=%s;export A;exec %s %s %s", X original, editor, endflag, tempfname); X X (void) system(pobuf); X} X X/* X * Do sanity checks after the author has typed in the message. X */ Xpost_checks() X{ X char group[BUFLEN]; X register char *c, *p; X struct stat stbuf; X X if (stat(tempfname, &stbuf) < 0) { X printf("File deleted - no message posted.\n"); X (void) UNLINK(tempfname); X exit(1); X } X if (stbuf.st_size < 5) { X printf("File too small (<5 characters) - no message posted.\n"); X (void) UNLINK(tempfname); X exit(1); X } X X if (stbuf.st_mtime == fmodtime) { X printf("File not modified - no message posted.\n"); X (void) UNLINK(tempfname); X exit(1); X } X X /* X * Is this the right number? Most of the headers are yet to be added X */ X if (stbuf.st_size > 64000) { X printf("\nYour message will probably be truncated when it\n"); X printf("passes through a notesfile site, since it is\n"); X printf("greater than 64000 characters.\n\n"); X if (!askyes("Do you still want to post it? ","")) { X sprintf(ccname, "%s/dead.article", homedir); X save_article(); X (void) UNLINK(tempfname); X exit(1); X } X } X X /* X * get the newsgroups from the edited article, in X * case they were altered in the editor X */ X if (!article_line(tempfname, "Newsgroups: ", group)) { X nogroups: X printf("Not sending to any newsgroups - no message posted\n"); X sprintf(ccname, "%s/dead.article", homedir); X save_article(); X (void) UNLINK(tempfname); X exit(1); X } X c = &group[11]; X while (*c == ' ' || *c == '\t') X c++; X if (*c == '\0') X goto nogroups; X for (p = newsgroups; *c; c++) /* copy to newsgroups, w/o blanks */ X if (*c != ' ' && *c != '\t') X *p++ = *c; X *p = '\0'; X X /* Sanity checks for certain newsgroups */ X if (ngmatch(newsgroups, "all.wanted") && ngmatch(distribution,"world,na,usa,att,btl,eunet,aus")) { X printf("Is your message something that might go in your local\n"); X printf("newspaper, for example a used car ad, or an apartment\n"); X printf("for rent? "); X if (askyes("","")) { X printf("It's pointless to distribute your article widely, since\n"); X printf("people more than a hundred miles away won't be interested.\n"); X printf("Please use a more restricted distribution.\n"); X get_distribution("*None*"); X modify_article(tempfname, "Distribution: ", distribution,REPLACE); X } X } X X if (ngmatch(newsgroups, "rec.humor,!rec.humor.d")) { X if (askyes("Could this be offensive to anyone? ","")) { X getpr("Whom might it offend? ", group); X (void) sprintf(pobuf," - offensive to %s (rot 13)",group); X modify_article(tempfname, "Subject: ", pobuf, APPEND); X encode(tempfname); X } X } X X if (ngmatch(newsgroups, "comp.sources.all,!comp.sources.wanted")) { X if (!article_line(tempfname, "Subject: ", group)) { X nosubj: X printf("There seems to be no subject for this article.\n"); X getpr("Subject: ", subject); X modify_article(tempfname, "Subject: ", subject, REPLACE); X } else { X c = &group[8]; X while (*c == ' ' || *c == '\t') X c++; X if (*c == '\0') X goto nosubj; X strcpy(subject, c); X } X if (ngmatch(newsgroups, "all.wanted") || iswanted(subject)) { X printf("Requests for sources should not be posted to any of\n"); X printf("the comp.sources newsgroups, please post such requests\n"); X printf("to comp.sources.wanted only. Please reenter the newsgroups.\n\n"); X while (!get_newsgroup()) X ; X modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE); X } X if (ngmatch(newsgroups, "comp.sources.all")) { X if (!ngmatch(newsgroups, "comp.sources.wanted") && X stbuf.st_size < (4*1024)) { X printf("Your article seems rather small to be a source distribution.\n"); X if (!askyes("Are you certain that this is really source? ", "")) { X X while (!get_newsgroup()) X ; X modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE); X } X } X if (index(newsgroups, NGDELIM)) { X printf("Sources should be posted to one newsgroup only.\n"); X printf("Please pick the most appropriate group for your article.\n\n"); X while (!get_newsgroup()) X ; X modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE); X } X } X } X} X Xiswanted(str) Xregister char *str; X{ X while (*str == ' ') X str++; X X if (prefix(str, "Re:")) X return (FALSE); X X if (isin(str, " wanted ") || isin(str, " can any") || X isin(str, " need ") || isin(str, " please ") || isin(str, " help ") X || isin(str, " looking ") || index(str, '?')) X return (TRUE); X X return (FALSE); X} X Xisin(str, words) Xregister char *str, *words; X{ X register char *p; X register sc, wc; X X p = words; X while (sc = *str++) { X if ((wc = *p++) == '\0') X return (TRUE); X if (wc == ' ') { X if (index(".,!?-; \t\n", sc)) X continue; X } else { X if (isupper(wc)) X wc = tolower(wc); X if (isupper(sc)) X sc = tolower(sc); X if (wc == sc) X continue; X } X str -= p - words - 1; X p = words; X } X if (*p == '\0') X return (TRUE); X return (FALSE); X} X X/* X * Save a copy of the article in the users NEWSARCHIVE directory. X */ Xsave_article() X{ X FILE *in, *out; X int c; X time_t timenow, time(); X char *today, *ctime(); X struct stat stbuf; X char filename[BUFLEN]; X X if (stat(ccname, &stbuf) == 0 && (stbuf.st_mode&S_IFMT) == S_IFDIR) { X /* X * It would be much nicer here to write articles X * in MH format (numbered files, in rfc822 format) X * X * one day .. X */ X (void) sprintf(filename, "%s/author_copy", ccname); X (void) strcpy(ccname, filename); X } X in = xfopen(tempfname, "r"); X out = xfopen(ccname, "a"); X timenow = time((time_t)0); X today = ctime(&timenow); X fprintf(out,"From postnews %s",today); X while ((c=getc(in)) != EOF) X putc(c, out); X putc('\n', out); X (void) fclose(in); X (void) fclose(out); X} X X/* X * Post the article to the net. X */ Xpost_article() X{ X int status; X X printf("Posting article...\n"); X fflush(stdout); X (void) sprintf(pobuf, "exec %s/%s -h < %s", LIB, "inews", tempfname); X status = system(pobuf); X X if (status) { X printf("Article not posted - exit status %d\n", status); X return; X } else X printf("Article posted successfully.\n"); X X if (ccname[0]) { X printf("A copy has been saved in %s\n", ccname); X save_article(); X } X X (void) UNLINK(tempfname); X exit(0); X} X X/* X * Initialization. X */ Xinit() X{ X FILE *fd; X register char *p; X int i; X char *getenv(); X struct passwd *pw; X X references[0] = '\0'; X distribution[0] = '\0'; X X uid = getuid(); X pw = getpwuid(uid); X if (pw == NULL) { X fprintf(stderr,"You're not in /etc/passwd\n"); X exit(1); X } X p = getenv("HOME"); X if (p == NULL) { X p = getenv("LOGDIR"); X if (p == NULL) X p = pw->pw_dir; X } X (void) strncpy(user, pw->pw_name, SBUFLEN); X (void) strcpy(homedir, p); X X p = getenv("NEWSARCHIVE"); X if (p != NULL) { X if (*p == '\0') X sprintf(ccname, "%s/author_copy", homedir); X else X strcpy(ccname, p); X } X X pathinit(); X (void) sprintf(pobuf, "%s/%s", LIB, "distributions"); X fd = xfopen(pobuf, "r"); X for (i=0; i < MAXDISTR; i++) { X if (fscanf(fd, "%s %[^\n]", distr[i].abbr, distr[i].descr) X != 2) X break; X if (strcmp(distr[i].abbr, "default") == 0) X strcpy(def_distr, distr[i--].descr); X } X (void) fclose(fd); X distr[i].abbr[0] = '\0'; X if (def_distr[0] == '\0') X strcpy(def_distr, "world"); /* maybe "local" is better? */ X} X X/* X * Get a yes or no answer to a question. A default may be used. X */ Xaskyes(msg, def) Xchar *msg, *def; X{ X for(;;) { X printf("%s", msg); X pobuf[0] = 0; X (void) gets(pobuf); X switch(pobuf[0]) { X case 'y': X case 'Y': X return TRUE; X case 'n': X case 'N': X return FALSE; X case '\0': X switch(*def) { X case 'y': X case 'Y': X return TRUE; X case 'n': X case 'N': X return FALSE; X } X default: X printf("Please answer yes or no.\n"); X } X } X} X X/* X * Get a character string into pobuf, using prompt msg. X */ Xgetpr(msg, bptr) Xchar *msg, *bptr; X{ X static int numeof = 0; X printf("%s", msg); X (void) gets(bptr); X (void) nstrip(bptr); X if (feof(stdin)) { X if (numeof++ > 3) { X fprintf(stderr,"Too many EOFs\n"); X exit(1); X } X clearerr(stdin); X } X} X Xbyebye(mesg) Xchar *mesg; X{ X printf("%s\n", mesg); X exit(1); X} X X/* X * make a modification to the header of an article X * X * fname -- name of article X * field -- header field to modify X * line -- modification line X * how -- APPEND or REPLACE X * X * example: X * modify_article("/tmp/article" , "Subject:" , "new subject" , REPLACE); X * X * X */ Xmodify_article(fname, field, line, how) Xchar *fname, *field, *line; X{ X FILE *fpart, *fptmp; X char *temp2fname = "/tmp/postXXXXXX"; X char lbfr[BUFLEN]; X register found = FALSE; X X mktemp(temp2fname); X X fptmp = xfopen(temp2fname, "w"); X fpart = xfopen(fname, "r"); X X while (fgets(lbfr, BUFLEN, fpart) != NULL) { X if (prefix(lbfr, field)) { X found = TRUE; X (void) nstrip(lbfr); X if (how == APPEND) { X /* append to current field */ X (void) strcat(lbfr, line); X (void) strcat(lbfr, "\n"); X } else X /* replace current field */ X (void) sprintf(lbfr, "%s%s\n", field, line); X } X (void) fputs(lbfr, fptmp); X } X X fclose(fpart); X fclose(fptmp); X X fptmp = xfopen(temp2fname, "r"); X fpart = xfopen(fname, "w"); X X if (!found) X fprintf(fpart, "%s%s\n", field, line); X while (fgets(pobuf,BUFLEN,fptmp) != NULL) X (void) fputs(pobuf, fpart); X X (void) fclose(fpart); X (void) fclose(fptmp); X (void) UNLINK(temp2fname); X} X X X/* verify that newsgroup exists, and get number of entries */ Xvalid_ng(ng, maxart, minart, canpost) Xchar *ng; Xlong *maxart, *minart; Xchar *canpost; X{ X char ng_check[BUFLEN], ng_read[BUFLEN]; X FILE *fp; X X fp = xfopen(ACTIVE, "r"); X while (fgets(ng_read, BUFLEN, fp) != NULL) { X switch (sscanf(ng_read, "%s %ld %ld %c", ng_check, maxart, minart, canpost)) { X case 2: X *minart = 1; X /* fall through */ X case 3: X *canpost = 'y'; X /* fall through */ X case 4: X break; X X default: X printf("Active file (%s) corrupted. ", ACTIVE); X byebye("Seek help!"); X } X X if (strcmp(ng_check, ng) == 0) { X (void) fclose(fp); X if (*canpost != 'n') { X#ifdef FASCIST X if (uid && uid != ROOTID && fascist(user, ng)) { X *canpost = 'n'; X return FALSE; X } X#endif /* FASCIST */ X return TRUE; X } else X return FALSE; X } X } X *canpost = 'i'; X *maxart = 0; X *minart = 0; X (void) fclose(fp); X return FALSE; X} X X/* get the line specified by field from an article */ Xarticle_line(article, field, line) Xchar *article, *field, *line; X{ X FILE *fp; X char *c; X X fp = xfopen(article,"r"); X while ((c=fgets(line,BUFLEN,fp)) != NULL && !prefix(line, field)) X if (line[0] == '\n') { X c = NULL; X break; X } X (void) fclose(fp); X if (c != NULL) { X (void) nstrip(line); X return TRUE; X } else { X line[0] = '\0'; X return FALSE; X } X} X X/* get the header information for a followup article */ Xfollowup(baseart) Xregister char *baseart; X{ X register char *p; X X /* subject */ X if (article_line(baseart, "Subject: ", pobuf)) { X p = pobuf+9; X for ( ; ; ) { X while (*p == ' ' || *p == '\t') X ++p; X if ((*p != 'r' && *p != 'R') || X (p[1] != 'e' && p[1] != 'E') || X (p[2] != ':' && p[2] != ' ')) X break; X p += 3; X } X (void) sprintf(subject, "Re: %s", p); X } else { X if (article_line(baseart, "From: ", pobuf)) X (void) sprintf(subject, "Re: orphan response from %s", pobuf); X else X (void) strcpy(subject, "Re: orphan response"); X } X X /* newsgroup */ X if (article_line(baseart, "Newsgroups: ", pobuf)) X (void) strcpy(newsgroups, pobuf+12); X if (ngmatch(newsgroups, "misc.jobs")) { X printf("misc.jobs is for the direct posting of job announcements and requests.\n"); X printf("it is not for discussion. You followup has been directed to misc.misc\n"); X (void) strcpy(newsgroups,"misc.misc"); X } X X /* distribution */ X if (article_line(baseart, "Distribution: ", pobuf)) X (void) strcpy(distribution, pobuf+14); X X /* references */ X if (article_line(baseart, "References: ", pobuf)) { X register char *rcp; X (void) strcpy(references, pobuf+12); X (void) strcat(references, " "); X /* keep the number of references to a reasonable number */ X rcp = rindex(references, ' '); /* Can not fail */ X while ((int)(rcp - references) > 70) { X while (*--rcp != ' ') X ; X rcp[1] = '\0'; X } X } X if (article_line(baseart, "Message-ID: ", pobuf)) { X (void) strcat(references, pobuf+12); X (void) strcpy(msgid, pobuf+12); X } X X if (article_line(baseart, "From: ", pobuf)) X (void) strcpy(isfrom, pobuf+6); X X if (article_line(baseart, "Keywords: ", pobuf)) X (void) strcpy(keywords, pobuf+10); X X if (article_line(baseart, "Followup-To: ", pobuf)) { X (void) strcpy(newsgroups, pobuf+13); X if (strcmp(newsgroups, "poster") == 0) X byebye("Mail followups directly to poster."); X } X X get_summary(); X} X Xget_summary() X{ X register char *p; X register i; X X printf("Please enter a short summary of your contribution to the discussion\n"); X printf("Just one or two lines ... (end with a blank line)\n"); X p = summary; X for (i = 0; i < 3; i++) { /* 3 * 80 < 256, should be safe .. */ X getpr(">\t", p); X if (*p == '\0') X break; X p = index(p, '\0'); X (void) strcpy(p, "\n\t "); X p += 3; X } X if (p > summary) X p[-3] = '\0'; X} X Xencode(article) Xchar *article; X{ X FILE *fpart, *fphead, *fpcoded; X char *headerfile = "/tmp/pheadXXXXXX"; X char *codedfile = "/tmp/pcodeXXXXXX"; X X (void) mktemp(headerfile); X (void) mktemp(codedfile); X X fpart = xfopen(article, "r"); X X /* place article header in "headerfile" file */ X fphead = xfopen(headerfile, "w"); X while (fgets(pobuf, BUFLEN, fpart) != NULL) { X (void) fputs(pobuf, fphead); X if (pobuf[0] == '\n') X break; X } X (void) fclose(fphead); X X /* place article body in "codedfile" file */ X fpcoded = xfopen(codedfile, "w"); X while (fgets(pobuf, BUFLEN, fpart) != NULL) X (void) fputs(pobuf, fpcoded); X (void) fclose(fpcoded); X (void) fclose(fpart); X X /* encode body and put back together with header */ X (void) rename(headerfile, article); X X (void) sprintf(pobuf,"exec %s/%s 13 < %s >> %s\n", LIB, "caesar", codedfile, article); X printf("Encoding article -- please stand by\n"); X (void) fflush(stdout); X if (system(pobuf)) { X printf("encoding failed"); X exit(2); X } X (void) UNLINK(codedfile); X} X X X/* X * Print a recorded message warning the poor luser what he is doing X * and demand that he understands it before proceeding. Only do X * this for newsgroups listed in LIBDIR/recording. X */ Xrecording(ngrps) Xchar *ngrps; X{ X char recbuf[BUFLEN]; X FILE *fd; X char nglist[BUFLEN], fname[BUFLEN]; X int c, n, yes, retval = 0; X X (void) sprintf(recbuf, "%s/%s", LIB, "recording"); X fd = fopen(recbuf, "r"); X if (fd == NULL) X return 0; X while ((fgets(recbuf, sizeof recbuf, fd)) != NULL) { X (void) sscanf(recbuf, "%s %s", nglist, fname); X if (ngmatch(ngrps, nglist)) { X (void) fclose(fd); X if (fname[0] == '/') X (void) strcpy(recbuf, fname); X else X (void) sprintf(recbuf, "%s/%s", LIB, fname); X fd = fopen(recbuf, "r"); X if (fd == NULL) X return 0; X while ((c = getc(fd)) != EOF) X putc(c, stderr); X fprintf(stderr, "Do you understand this? Hit to proceed, to abort: "); X n = read(2, recbuf, 100); X c = recbuf[0]; X yes = (c=='y' || c=='Y' || c=='\n' || c=='\n' || c==0); X if (n <= 0 || !yes) X retval = -1; X } X } X return retval; X} X Xxxit(i) X{ X exit(i); X} X X#if !defined(BSD4_2) && !defined(BSD4_1C) Xrename(from,to) Xregister char *from, *to; X{ X (void) unlink(to); X if (link(from, to) < 0) X return -1; X X (void) unlink(from); X return 0; X} X#endif /* !BSD4_2 && ! BSD4_1C */ END_OF_FILE if test 26497 -ne `wc -c <'postnews.c'`; then echo shar: \"'postnews.c'\" unpacked with wrong size! fi # end of 'postnews.c' fi if test -f 'getdate.s.uu' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'getdate.s.uu'\" else echo shar: Extracting \"'getdate.s.uu'\" \(26072 characters\) sed "s/^X//" >'getdate.s.uu' <<'END_OF_FILE' Xbegin 644 getdate.s XMK@I?;61A>7,Z"L(S,0JX"L(S,0K",S *PC,Q"L(S, K",S$*PC,Q"L(S, K" XM,S$*PC,P"LE?9&%T96-O;G8*PC,Q"H8*7V1A=&5C;VYV.@J#"H(*U_(L(S$P XM"L'O"L'P"L#IU IO7/'"F-W9 K$Y-@*861C(.?0"L#8+.L* XMP- L[@K<[PJ:. I),# Q,34Z"FUO=B!S:2PC,3DW, I),# Q,4,Z"LWI[PIJ XM;&4@23 P,3$Y"L#C- K Y.\*8W=D"FGP=B#M"H<*;W(@Y^X*V3%F"MSK"C$Z XM"L3A,S8U"F-W9 K$Y-@*861C(.?0"L#8+.L*P- L[@K<[PJ:0PI),# Q,3DZ XM"K0P.#8T"L#G(S$*P= *P=@*TRYM;&DT"L#8+.L*P- L[@K Y#'4"F-W9 K! XMT K!V J<"H *P.$V, K+Y^X*TRYM;&DT"L/M"HD*Q.;K"F%D8R#E[@K V"SM XM"L#0+.P*P3'."L$QQ0K!,3(H\2D*P3$P*/$I"M-?=&EM96-O;G8*Q/(L(S@* XMK K QBSN"LW&]@IJ9V4@23 P,3%%"L#A+3$*@ K X38U-3,U"H *F@I),# Q XM,44Z"J,*P.;&"L38+.L*861C(- L[0K-,C H\2DL(S$*L3 *S3(P*/$I+",S XM"ME),# Q,C$*V^38"H *TU]L;V-A;'1I;64*B0J["LTQ-L?V"K$Q"DDP,#$R XM,#H*Q-@L(S8Q.3,V"F%D8R#0+",M,0I),# Q,C$Z"L'0"L'8"I\*C0K#[@K, XM+F1S@0K)7V1A>6-O;G8*7V1A>6-O;G8Z"H,*@@K7\BPC-@K![PK!\ K Z<4* XMP.0X*&)P*0IM;W8@8W@L,3 H\2D*P- LZPK SRSM"MODT J "M-?;&]C86QT XM:6UE"HD*P.CK"L#DS@K7Y#$R*.\I"L3A-PK XS<*8W=D"FGP=B#M"L#D[@IC XM=V0*N0K!T J<"H *M# X-C0*P.X*P- L[0K SRSL"L$Q,"CQ*0K!U JY"L'0"M-? XM9&%Y;&-ODC-3D*:FQE($DP,#,S"DDP,#,R.@K XMX2TQ"H *P.$V-34S-0J "LQ),# S,0I),# S,SH*P3$P*/$I"LQ),# S. I) XM,# S03H*;W(@Z.\*:FQE($DP,#-""LWH(S$R"FIL92!),# S0PI),# S0CH* XM;6]V(&%X+",M,0J "L#A-C4U,S4*@ K,23 P,S$*23 P,T,Z"L#C,3(*P.3O XM"F-W9 II\'8@[0K Y.X*8W=D"IP*@ K X38P"LOG[@K3+FUL:30*G J "L#D XMS@IC=V0*P^T*B0K$YNL*861C(.7N"L#A-C *R^?N"J8*P>T*TRYM;&DT"IP* XM@ K Y/ *8W=D"L/M"HD*Q.;K"F%D8R#E[@JF"L'M"LQ),# S,0I),# S1CH* XM;W(@Z.\*:FQE($DP,#,Q, K-Z",Q,@IJ;&4@23 P,S$Q"DDP,#,Q,#H*P.$M XM,0J "L#A-C4U,S4*@ K,23 P,S$*23 P,S$Q.@K XS$R"L#D[PIC=V0*:?!V XM(.T*Q.X*I@K![0K,23 P,S$*23 P,S$T.@IO XM@C,C,*:FQE($DP,#,Q-@I),# S,34Z"L#A+3$* XM@ K X38U-3,U"H *S$DP,#,Q"DDP,#,Q-CH*P.3O"F-W9 J<"H *P.$V, K+ XMY^X*TRYM;&DT"IP*@ K Y,X*8W=D"L/M"HD*Q.9A> IA9&,@8G@L9'@*P.$V XM, K+Y^X*I@K![0K3+FUL:30*G J "L#D\ IC=V0*P^T*B0K$YNL*861C(.7N XM"J8*P>T*S$DP,#,Q"DDP,#,Q.3H*P.$M,0J "L#A-C4U,S4*@ K,23 P,S$* XM23 P,S@Z"L#B7S$*C0K,+F-S8C(*23 P,S$Z"HT*P^X*S"YD\*P? *V^34"H *TU]L;V-A;'1I;64*B0IM;W8@ XM8G@L87@*;6]V(.0TQPKX*P.3M"L#G[ K,+F1S@0K)7WEY;&5X"E]Y>6QE>#H*@PJ" XM"M?R+",R. K![PK!\ I),# V-SH*P.5?;'!T<@J,"HL*NPK*86PL7U]C='EP XM95\K,<<*BPIT97-T8B!A;"PC. IJ92!),# V-@K<7VQP='(*S$DP,#8W"DDP XM,#8V.@K Y5]L<'1R"HP*RBTS*/$I+&%L"HL*NPK*86PL7U]C='EP95\K,<<* XMBPIT97-T8B!A;"PC- K923 P-CD*8VUP8B M,RCQ*2PC-#4*:F4@23 P-CD* XM8VUP8B M,RCQ*2PC-#,*V4DP,#9!"DDP,#8Y.@IC;7!B("TS*/$I+",T-0IJ XM92!),# V10IC;7!B("TS*/$I+",T,PK923 P-D8*23 P-D4Z"F-M<&(@+3,H XM\2DL(S0U"ME),# V,3,*P,8L(RTQ"LQ),# V,30*23 P-C$S.@K QBPC,0I) XM,# V,30Z"MQ?;'!T<@K Y5]L<'1R"HP*BPJ["LIA;"Q?7V-T>7!E7RLQQPJ+ XM"G1E6QE> J "LQ),# V,0I),# V1CH* XMP,8L(S$*23 P-C$P.@K 7WEY;'9A;/8*23 P-C$Y.@IM;W8@8G@L7VQP='(* XMW%]L<'1R"HP*RBTS*/$I+&%L"HL*NPK*86PL7U]C='EP95\K,<<*BPIT97-T XM8B!A;"PC- IJ92!),# V,3@*RF%L+"TS*/$I"HL*@ J/, IM=6P@7WEY;'9A XM; K#[0K$YNL*U^,T. K 7WEY;'9A;"SM"LQ),# V,3D*23 P-C$X.@K Y%]Y XM>6QV86P*;75L(,8*P%]Y>6QV86PLZPKS7VQP='(*M#8Q"H *S$DP,#8Q"DDP XM,#9!.@K*86PL+3,H\2D*BPJ["LIA;"Q?7V-T>7!E7RLQQPJ+"G1E"Q?;'!T<@II;F,@ XM7VQP='(*C J+"H *23 P-C$Z"HT*S"YDF]N XM93H*PE\Q,3<*PC(V-0K"-C *PE\Q,3@*PC(V-0K",3(P"L)?,3$Y"L(R-C4* XMPC$X, K"7S$R, K",C8U"L(R-# *PE\Q,C$*PC(V-0K",S P"L)?,3(R"L(R XM-C4*PC,V, K"7S$R,PK",C8U"L(T,C *PE\Q,C0*PC(V-0K"-#@P"L)?,3(U XM"L(R-C4*PC4T, K"7S$R-@K",C8U"L(V,# *PE\Q,C<*PC(V-0K"-C8P"L)? XM,3(X"L(R-C4*PC\*P? *B K;Y"TQ,M0*@ K37W-T0J)"HD*V^0M,3+4"L M,3,P XM*/$I+.L*H@KSZPK Z>L*23 P-S,Z"MSP"F-M<&(@*/ I]@IJ92!),# W,@K* XM86PL*/ I"HL*NPK*86PL7U]C='EP95\K,<<*BPIT97-T8B!A;"PC,0IJ92!) XM,# W-@K*86PL*/ I"HL*@ K37W1O;&]W97(*B0J "LQ),# W-PI),# W-CH* XMRF%L+"CP*0J+"H *23 P-S$S"ME),# W.0K +3$SSBPC,0K,23 P-T$*23 P-SDZ"MOD+3$RU J "M-? XML*P.0H[RD*P"TQ,S H\2DLZPI),# W,38Z"L#E+3$S,"CQ*0K<+3$S XM,"CQ*0J,"HL*P.7P"MSP"H *C J+"L/M"LWFZPK923 P-S$P"LTM,3/.]@IJ XM92!),# W,3@*P.4H[RD*Q.(S"LTM,3,P*/$I+.P*V4DP,#6QV86PL[0K!,BCO*0K,23 P-S$*23 P-S$X.@K Y2TQ,S H\2D*8VUP XM8B M,7EL=F%L+.T*P3(H[RD*S$DP,#G1A8@I),# W,C@Z"LTH XM[RGV"FIE($DP,#7EL=F%L+.T*P3(H[RD*S$DP,#F]N969L86F]N92SM"L!?9&%Y;&EG:'0L XM(S,*P%]S<_8*P.9?69L8669L86?V"FIE($DP,#@Q. I),# X,3X*C0K#[@K7Y.T*65R XM65R65X8V$Z"L(M XM,0K",0JX"L(M,0K"+3(*R5]Y>6%C= JX"E]Y>6%C=#H*PC$R"L(Q,PK",C$* XMPCD*PC$T"L(Q-0K",38*PC$P"L(Q,0K",S0*PC$W"L(S.0K"-# *PC$Y"L(S XM. K",S<*PC,V"L(S, K",CD*PC(X"L(R-@K",S4*PC,Q"L(R-PK". K"-PK" XM-@K"-0K"- K",PK",@K",0JX"K@*N JX"K@*N JX"K@*N JX"K@*N JX"K@* XMN JX"K@*N JX"K@*N JX"K@*N JX"K@*N JX"BYW;W)D(# *+G=O7!A8W0*PC(U"E]Y>7!A8W0Z XM"L(M,3 P, K"+3(U. K"+3$P,# *PBTQ,# P"L(M,3 P, K"+3$P,# *PBTQ XM,# P"L(M,C4W"L(M,3 P, K"+30U"L(M,3 P, K"+3$P,# *PBTR-#$*PBTR XM,0K"+3$P,# *PBTQ,# P"L(M,3 P, K"+3$P,# *PBTQ,# P"L(M,C0R"L(M XM,3 P, K"+3(T,PK"+3(T- K"+3$P,# *PBTQ,# P"L(M,3 P, K"+3(R"L(M XM,3 P, K"+30Y"L(M,C8*PBTQ,# P"L(M,C0U"L(M,3 P, K"+3$P,# *PBTR XM-#8*PBTR-#<*PBTQ,# P"L(M,C0Y"L(M,3 P, K"+3$P,# *R5]Y>7!G;PK" XM+3$P,# *7WEY<&=O.@JX"L(S,0K",S *PC(Y"L(R. K",C<*PC(V"L(R-0K) XM7WEY7(Q.@JX"L(Q"L(Q"L(R"L(R"L(R"L(R"L(R"L(R"L(X XM"L(S"L(S"L(S"L(S"L(S"L(S"L(S"L(T"BYW;W)D(#0*+G=O6-H:SH*PBTQ,# P XM"L(M,0K"+3(*PBTS"L(M- K"+34*PBTV"L(M-PK"+3@*PC(V,0K",C8U"L(R XM-C8*PC(U. K",C4Y"L(R-C(*PC(V,PK",C8T"L(R-C<*PC(V, K"-3@*PC(U XM.0K"-#<*PC(U. K",C8R"L(R-C,*PC(V- K",C8Q"L(T- K",C8Q"L(R-C$* XMPC(V,0K"-#0*PC(V, K",C8Q"L(U. K"-#<*PC(V,0K",C8Q"L(R-C$*PC(V XM, K)7WEY9&5F"L(R-C$*7WEY9&5F.@K",0K"+3(*PC(*PC,*PC0*PC4*PC8* XMPC<*PC@*PCD*PC$W"L(Q. JX"L(Q.0K",S$*PC,R"L(S,PK",S0*+G=O6YE7EN97)R65R7EE7!A6-H87(L(RTQ XM"L!?>7EN97)R<_8*P%]Y>65R65RDC+3$P,# *:F<@23 P03@*S$DP,$%!"DDP,$$X.@K-7WEY8VAA XM7EL97@*P%]Y>6-H87(LZPK-7WEY8VAA7EC:&%R]@I),#!!0SH*Q.E?>7EC:&%R"F]R(.GP"FIL($DP XM,$%!"LWI(S(R, IJ;"!),#!!,3(*S$DP,$%!"DDP,$$Q,CH*P.7P"G-A;"#B XM,0K Z5]Y>6%C=,<*P.7P"G-A;"#B,0K YE]Y>6-H87(*S5]Y>6-H:\6-H87(L(RTQ"L#F7WEY;'9A; K 7WEY=F%L+.T*P"TS,-0L XM\ K-7WEY97)R9FQA9_8*:FQE($DP,$$R"O-?>7EE61E9L<*S>DC+3(*V4DP,$$Q0PK- XM7WEY8VAA7EC:&%R+.L*S5]Y>6-H XM87+V"FIG92!),#!!,48*P%]Y>6-H87+V"DDP,$$Q1CH*P"TS,65X XM8V$*23 P03(W.@K Y2TS,"PM XM,S X*&)P*0IC;7 @,L7EE7!A8W3'"L3A,C4V"L#IZPIODC,C(P"FIG92!),#!!,T8*P.7P"G-A;"#B,0K Y5]Y>6%C XM=,<*7EC:&O'+",R-38*V4DP,$$S1@K Y? *7EC:&%R]@K923 P XM030V"LQ),#!!-#,*23 P030V.@K 7WEY8VAA7(RQPIS86P@XC$*].P*Q.4M,S'%"L M,S'%+.P* XMP.4M,S'%"L#F,L<*P%]Y>79A;"SM"L M,S#%+/ *P.7P"G-A;"#B,0K Z5]Y XM>7(QQPK Y? *7EP9V_'"L#E+3,Q,"CQ*0J-"L3DQPK7EC:&O'+.L*:F4@23 P030Y"DDP,$$T.#H*P.7P"G-A;"#B,0K Y5]Y XM>7!G;\<*6QI9VAT+",R"L#C,3 P"L#D*.\I"F-W XM9 II\'8@[0K XC8P"FUU;"#L"H *P.0H[RD*8W=D"FGP=B#M"L/M"L3F[@KT XM[0K 7V]U6QI9VAT+",Q"LQ),#!!,@I),#!!-C(Z"L!?9&%Y;W)D+",Q"L#F*.\I XM"L!?9&%Y7)E<2SM"LQ),#!!,@I),#!!-C0Z"L#F+3(H[RD*P%]D87EO7)E<2SM"LQ),#!!,@I),#!!-C4Z"L#F+30H[RD*P%]M XM;VYT:"SM"L#F*.\I"L!?9&%Y+.T*S$DP,$$R"DDP,$$V-CH*P.8M."CO*0K XM7VUO;G1H+.T*P.8M-"CO*0K 7V1A>2SM"L#F*.\I"L!?>65A2SM XM"L#F*.\I"L!?>65A2SM"L#F*.\I"L!?>65AX*P%]R96QS96,L[0K 7W)E;'-E8RLR+.P*S$DP,$$R"DDP,$$V0SH* XM;6]V(&%X+"CO*0IM=6P@+3(H[RD*8W=D"L3D7W)E;&UO;G1H"F%D8R#G7W)E XM;&UO;G1H*S(*P%]R96QM;VYT:"SK"L!?78Z("YZ XM97)O=R S,# O,@I?;'!T79A;#H@ XM+GIE7EL=F%L.B N>F5R;W<@,B\R"E]O=7)Z XM;VYE.B N>F5R;W<@,B\R"E]Y96%R.B N>F5R;W<@,B\R"E]D87DZ("YZ97)O XM=R R+S(*7VUO;G1H.B N>F5R;W<@,B\R"E]D87ER97$Z("YZ97)O=R R+S(* XM7V1A>6]R9#H@+GIEF5R;W<@,B\R"E]SF5R;W<@,B\R"E]R96QM;VYT:#H@+GIEF5R;W<@-"\R"E]R96QF;&%G.B N>F5R;W<@,B\R"E]D87EF;&%G XM.B N>F5R;W<@,B\R"E]D871E9FQA9SH@+GIEF]N969L86F5R;W<@,B\R"JX*7S(Z"L(R-#DS XM. K",S P-C(*PC(Y,C@Q"L(Q,C$*7S,Z"L(R-3DU. K",CDR.#(*PC(T.30Y XM"L(S,3 Y, JX"E\T.@K",C0Y-#$*PC(U-#4X"L(Q,#0*7S4Z"L(R.#