home *** CD-ROM | disk | FTP | other *** search
- /*
- * This software is Copyright 1986, 1989 by Rick Adams.
- *
- * Permission is hereby granted to copy, reproduce, redistribute or
- * otherwise use this software as long as: there is no monetary
- * profit gained specifically from the use or reproduction or this
- * software, it is not sold, rented, traded or otherwise marketed, and
- * this copyright notice is included prominently in any copy
- * made.
- *
- * The author make no claims as to the fitness or correctness of
- * this software for any use whatsoever, and it is provided as is.
- * Any use of this software is at the user's own risk.
- *
- * Postnews: post a news message to Usenet. This C version replaces a shell
- * script, and does more intelligent prompting and filtering than possible
- * in a shell script.
- *
- * Ported to the Amiga by Ingo Feulner 1990.
- *
- * 2 Oct 90: Fixed a bug in the date routine.
- *
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <errno.h>
-
- #ifdef AMIGA
- #include <dos.h>
- #include <time.h>
- // #include "unix.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "include/config.h"
- #include "postnews.h"
- // #include "system.h"
-
-
- #define MKTEMP mktemp
- #define UNLINK remove
- #define perror poserr
- #define DFTEDITOR "c:ed"
-
- #define LBUFLEN 1024
- #define BUFLEN 512
- #define MBUFLEN 256
- #define SBUFLEN 32
-
- #define NGDELIM ','
- #define NEGCHAR '!'
-
- extern char *__regargs mktemp(char *);
-
- #define index strchr
- #define rindex strrchr
- char *_TZ;
-
- FILE *xfopen(char *, char *);
- void copydists(char *, char *, char *);
-
- static char *version20 = "$VER: postnews 1.03 (2 Oct 90)\n\r";
-
- #endif /* AMIGA */
-
- #define APPEND 1
- #define REPLACE 2
-
-
- char tempfname[50]; /* file name used for making article */
- char original[MBUFLEN]; /* file name of original, used in followup */
-
- #ifndef AMIGA
- char user[SBUFLEN]; /* user name */
- #else
- char *newsdir; /* news directory */
- char *activefile; /* full path of active file */
- char *newslibdir; /* news lib directory */
- char *bugfile; /* full path of bug file */
-
- char *user; /* user name */
- char *realname; /* user realname */
- char *node; /* node */
- char *domain; /* node domain */
- char *messageid; /* messageid */
- char *organization; /* organization */
- char *path; /* posting path */
-
- char curpath[256]; /* Path postnews was called from */
-
- char approve_able = 1; /* Should we check if the user has inserted
- an 'Approved:' line in the header?
- Only NEW article.
- */
- #endif /* !AMIGA */
-
- char ccname[MBUFLEN]; /* file name for article copy */
-
- /* article header information */
- char subject[MBUFLEN];
- char distribution[MBUFLEN];
- char references[BUFLEN];
- char newsgroups[BUFLEN];
- char followto[MBUFLEN];
- char isfrom[MBUFLEN];
- char msgid[MBUFLEN];
- char keywords[MBUFLEN];
- char summary[BUFLEN];
- char approved[MBUFLEN];
-
- char ngsep[] = { NGDELIM, '\0' }; /* == "," */
-
- char *Progname = "postnews"; /* for xerror */
-
- time_t fmodtime;
- char buf[BUFLEN];
-
- #define MAXDISTR 16
- struct distr
- {
- char abbr[24];
- char descr[128];
- } distr[MAXDISTR];
-
- char def_distr[24] = ""; /* default distribution */
-
- void xerror(char *txt, long arg1, long arg2, long arg3)
- {
- char buffer[BUFLEN];
-
- (void)sprintf(buffer, txt, arg1, arg2, arg3);
- (void)fprintf(stderr, buffer);
- xxit(1);
- }
-
-
- void main(int argc, char *argv[])
- {
- int c;
-
- init();
-
- if (argc == 2)
- {
- approve_able = 0; /* Check not for 'Approved' line -IF- */
-
- if (!prefix(argv[1], newsdir))
- xerror("Can only followup to articles in %s\n", newsdir);
-
- followup(argv[1]);
- (void) strcpy(original, argv[1]);
-
- }
- else
- {
- if (askyes("Is this message in response to some other message? ","no"))
- {
- char ng[BUFLEN], num[BUFLEN];
- long i, j, lastnum;
- char *p;
- int fd, dir;
- char canpost;
-
- approve_able = 0;
-
- getpr("In what newsgroup was the article posted? ",ng);
- if (!valid_ng(ng, &i, &j, &canpost, TRUE))
- if (canpost == 'i' )
- byebye("There is no such newsgroup.");
- else if (canpost == 'n')
- byebye("You are not allowed to post to that group.");
-
- printf("Valid article numbers are from %ld to %ld\n", j, i);
- lastnum = i + 1;
- dir = -1;
-
- for(;;)
- {
- getpr("\nWhat was the article number? ", num);
- switch(num[0]) {
- case '+':
- dir = 1;
- sprintf(num, "%ld", lastnum + 1);
- break;
- case '-':
- dir = -1;
- /* no break */
- case '\0':
- sprintf(num, "%ld", lastnum + dir);
- break;
- }
-
- (void) strcpy(original, MakeConfigPath(UUNEWS, ng));
- for (p=original+strlen(newsdir)+1; *p ;++p)
- if (*p == '.')
- *p = '/';
- (void) strcat(original, "/");
- (void) strcat(original, num);
-
- if ((fd=open(original,0)) >= 0)
- {
- (void) close(fd);
-
- printf("\narticle %s\n", original);
-
- if (article_line(original, "From: ", buf))
- printf("%s\n", buf);
- if (article_line(original, "Subject: ", buf))
- printf("%s\n", buf);
- if (askyes("Is this the one you want? ", "n"))
- break;
- }
- else
- printf("I can't find that article.\n");
-
- lastnum = atol(num);
- }
-
- followup(original);
- }
- else
- {
- do
- {
- getpr("Subject: ", subject);
- if (*subject == '?')
- {
- printf("People read the subject line to learn what your article is about.\n");
- printf("You want it to do the same job as a newspaper headline.\n");
- printf("So type in something both brief and descriptive.\n");
- *subject = '\0';
- }
- } while (*subject == '\0');
- getpr("Keywords: ", keywords);
-
- while (!get_newsgroup())
- ;
- get_distribution((char *)0);
- }
- }
-
- if (pre_checks())
- xxit(1);
-
- prep_article();
- c = 'e';
- for (;;)
- {
- if (c == 'e')
- {
- edit_article();
- post_checks();
- }
- do
- {
- do
- {
- getpr("\nWhat now? [send, edit, list, quit, write, append] ", buf);
- c = buf[0];
- } while (c == '\0');
- if (isupper(c))
- c = tolower(c);
- if (c == 'q')
- {
- (void) UNLINK(tempfname);
- xxit(1);
- }
- if (c == 'l')
- {
- char *pager = getenv("PAGER");
-
- if (pager == NULL || *pager == '\0')
- {
- pager = "type";
- }
- sprintf(buf, "%s %s", pager, tempfname);
- (void)Execute(buf, 0, 0);
- }
- if (c == 'w' || c == 'a')
- {
- int ifd, ofd, nbytes;
- char iobuf[BUFSIZ];
- char fname[BUFLEN];
- getpr("Filename? ", fname);
- if (fname[0] == '\0')
- continue;
- ofd = (c == 'w') ? creat(fname, 0666)
- : open(fname, 2);
- if (ofd < 0)
- perror(fname);
- else
- {
- if (c == 'a')
- (void) lseek(ofd, 0L, 2);
- ifd = open(tempfname, 0);
- if (ifd < 0)
- xerror("Can't reopen %s\n", tempfname);
- while ((nbytes = read(ifd, iobuf, BUFSIZ)) > 0 )
- write(ofd, iobuf, nbytes);
- close(ofd);
- close(ifd);
- }
- }
- } while (!index("eps", c));
- if (c != 'e')
- post_article(); /* will exit if posted successfully */
- }
- }
-
- /*
- * Find out the topic of interest.
- */
- int get_newsgroup(void)
- {
- int n;
- long i;
- char canpost;
- static int first = 1;
-
- printf("Newsgroups (enter one at a time, end with a blank line):\n");
- if (first)
- {
- printf("\nThe most relevant newsgroup should be the first, you should\n");
- printf("add others only if your article really MUST be read by people\n");
- printf("who choose not to read the appropriate group for your article.\n");
- printf("But DO use multiple newsgroups rather than posting many times.\n\n");
- first = 0;
- }
-
- printf("For a list of newsgroups, type ?\n");
- n = 0;
- newsgroups[0] = '\0';
-
- for(;;)
- {
- getpr("> ", buf);
- if (buf[0] == '\0')
- if (n == 0)
- return FALSE;
- else
- return TRUE;
-
- if (buf[0] == '?')
- {
- char *pager = getenv("PAGER");
-
- if (pager == NULL)
- {
- pager = "type";
- }
- printf("These are the currently active groups:\n");
- (void) fflush(stdout);
-
- sprintf(buf, "%s %s/newsgroups", pager, newslibdir);
- (void) Execute(buf, 0, 0);
- continue;
- }
-
- if (valid_ng(buf, &i, &i, &canpost, FALSE))
- {
- if (n++ != 0)
- (void) strcat(newsgroups, ngsep);
- (void) strcat(newsgroups, buf);
- }
- else
- {
- if (canpost == 'n')
- printf("You are not allowed to post to %s\n", buf);
- else if (canpost == 'i')
- printf("%s is not a valid newsgroup.\n", buf);
- }
- }
- }
-
- /*
- * Find out how widely the author wants the message distributed.
- */
- void get_distribution(deflt)
- char *deflt;
- {
- int i;
- char *r;
- char def[BUFLEN];
- char *lastgroup;
-
- lastgroup = newsgroups;
- (void) strcpy(def, newsgroups);
- r = index(def, NGDELIM);
- if (r)
- *r = '\0';
- r = index(def, '.');
- if (r)
- {
- *r = '\0';
- if (strcmp(def, "net") == 0)
- (void) strcpy(def, "world");
- }
- else
- {
- distribution[0] = '\0';
- return;
- }
-
- if (strcmp(def, "to") == 0)
- {
- /*
- * This only works if "to.xx" is the first (or only)
- * newsgroup, but it usually is ..
- * Perhaps we should make the distribution be "to.xxx" ??
- */
- distribution[0] = '\0';
- return; /* He's probably testing something */
- }
- if (deflt != (char *)0)
- (void) strcpy(def, deflt);
- if (ngmatch("misc.test", newsgroups))
- (void) strcpy(def, "local");
- for (i=0; distr[i].abbr[0]; i++)
- {
- if (strcmp(distr[i].abbr, def) == 0)
- break;
- }
- if (distr[i].abbr[0] == '\0')
- strcpy(def, def_distr);
- for(;;)
- {
- do
- {
- (void) sprintf(buf, "Distribution (default='%s', '?' for help) : ", def);
- getpr(buf, distribution);
- if (distribution[0] == '\0')
- {
- if (strcmp(def, "*None*") == 0)
- printf("You must enter a distribution, '?' for help.\n");
- (void) strcpy(distribution, def);
- }
- } while (strcmp(distribution, "*None*") == 0);
-
- /* Did the user ask for help? */
- if (distribution[0] == '?')
- {
- printf("How widely should your article be distributed?\n\n");
- for (i=0; distr[i].abbr[0]; i++)
- printf("%s\t%s\n", distr[i].abbr, distr[i].descr);
- printf("\nEnter the word that specifies the distribution that you require.\n");
- continue;
- }
-
- /* Check that it's a proper distribution */
- for (i=0; distr[i].abbr[0]; i++)
- {
- if (strncmp(distr[i].abbr, distribution, sizeof(distr[0].abbr)) == 0)
- {
- return;
- }
- }
- if (strcmp(distribution, def) != 0)
- printf("Type ? for help.\n");
- else
- {
- int once = TRUE;
-
- do
- {
- r = lastgroup;
- while (r = index(r, NGDELIM))
- if (!prefix(++r, def))
- break;
- if (r == NULL)
- {
- /*
- * no newsgroups are distribution
- * names, and user simply will
- * not type a valid distribution,
- * assume that the default is OK.
- */
- distribution[0] = '\0';
- return;
- }
- lastgroup = r;
- if (once)
- printf("Sorry, '%s' is an unknown distribution. Type ? for help.\n", def);
- once = FALSE;
- strcpy(def, r);
- r = index(def, NGDELIM);
- if (r)
- *r = '\0';
- r = index(def, '.');
- } while (r == NULL);
- *r = '\0';
- if (strcmp(def, "net") == 0)
- strcpy(def, "world");
- }
- }
- }
-
- /*
- * Do sanity checks before the author types in the message.
- */
- int pre_checks(void)
- {
- if (recording(newsgroups))
- return 1;
- return 0;
- }
-
- /*
- * Set up the temp file with headers.
- */
- void prep_article(void)
- {
- FILE *tf, *of;
- struct stat stbuf;
-
- (void) strcpy(tempfname, "T:postXXXXXXXX");
- MKTEMP(tempfname);
-
- /* insert a header */
- tf = xfopen(tempfname, "w");
- fprintf(tf, "Subject: %s\n", subject);
- fprintf(tf, "Newsgroups: %s\n", newsgroups);
-
- if (followto[0] != '\0')
- fprintf(tf, "Followup-To: %s\n", followto);
-
- if (distribution[0] != '\0' && strcmp(distribution, "world"))
- fprintf(tf, "Distribution: %s\n", distribution);
-
- if (keywords[0] != '\0')
- fprintf(tf, "Keywords: %s\n", keywords);
-
- if (summary[0] != '\0')
- fprintf(tf, "Summary: %s\n", summary);
-
- if (references[0] != '\0') {
- fprintf(tf, "References: %s\n\n", references);
-
- if (askyes("Do you want to include a copy of the article? ", "no")){
- of = xfopen(original, "r");
- while (fgets(buf, BUFLEN, of) != NULL)
- if (buf[0] == '\n') /* skip headers */
- break;
- fprintf(tf, "In article %s, %s writes:\n", msgid, isfrom);
- while (fgets(buf, BUFLEN, of) != NULL)
- fprintf(tf, "> %s", buf);
- (void) fclose(of);
- printf("OK, but please edit it to suppress unnecessary verbiage, signatures, etc.\n");
- (void) fflush(stdout);
- }
- }
-
- fprintf(tf, "\n\n");
- (void) fflush(tf);
- (void) fclose(tf);
- (void) stat(tempfname, &stbuf);
- fmodtime = stbuf.st_mtime;
- }
-
- void edit_article(void)
- {
- char *editor;
- char buf[BUFLEN];
-
- /* edit the file */
- editor = FindConfig(NEWSEDITOR);
- if (editor == NULL)
- editor = DFTEDITOR;
-
- (void) sprintf(buf, "%s %s", editor, tempfname);
- (void) Execute(buf, 0, 0);
-
- if(approve_able == 1) /* Check for 'Approved:' line -IF- */
- {
- if(article_line(tempfname, "Approved: ", buf) == TRUE)
- strcpy(approved, &buf[10]);
- }
- }
-
- /*
- * Do sanity checks after the author has typed in the message.
- */
- void post_checks(void)
- {
- char group[BUFLEN];
- char *c, *p;
- struct stat stbuf;
-
- if (stat(tempfname, &stbuf) < 0)
- {
- printf("File deleted - no message posted.\n");
- (void) UNLINK(tempfname);
- xxit(1);
- }
- if (stbuf.st_size < 5)
- {
- printf("File too small (<5 characters) - no message posted.\n");
- (void) UNLINK(tempfname);
- xxit(1);
- }
-
- if (stbuf.st_mtime == fmodtime)
- {
- printf("File not modified - no message posted.\n");
- (void) UNLINK(tempfname);
- xxit(1);
- }
-
- /*
- * Is this the right number? Most of the headers are yet to be added
- */
- if (stbuf.st_size > 64000)
- {
- printf("\nYour message will probably be truncated when it\n");
- printf("passes through a notesfile site, since it is\n");
- printf("greater than 64000 characters.\n\n");
- if (!askyes("Do you still want to post it? ",""))
- {
- sprintf(ccname, "%s/dead.article", newslibdir);
- save_article();
- (void) UNLINK(tempfname);
- xxit(1);
- }
- }
-
- /*
- * get the newsgroups from the edited article, in
- * case they were altered in the editor
- */
- if (!article_line(tempfname, "Newsgroups: ", group))
- {
- nogroups:
- printf("Not sending to any newsgroups - no message posted\n");
- sprintf(ccname, "%s/dead.article", newslibdir);
- save_article();
- (void) UNLINK(tempfname);
- xxit(1);
- }
- c = &group[11];
- while (*c == ' ' || *c == '\t')
- c++;
- if (*c == '\0')
- goto nogroups;
- for (p = newsgroups; *c; c++) /* copy to newsgroups, w/o blanks */
- if (*c != ' ' && *c != '\t')
- *p++ = *c;
- *p = '\0';
-
- /* Sanity checks for certain newsgroups */
- if (ngmatch(newsgroups, "all.wanted") && ngmatch(distribution,"world,na,usa,att,btl,eunet,aus"))
- {
- printf("Is your message something that might go in your local\n");
- printf("newspaper, for example a used car ad, or an apartment\n");
- printf("for rent? ");
- if (askyes("",""))
- {
- printf("It's pointless to distribute your article widely, since\n");
- printf("people more than a hundred miles away won't be interested.\n");
- printf("Please use a more restricted distribution.\n");
- get_distribution("*None*");
- modify_article(tempfname, "Distribution: ", distribution,REPLACE);
- }
- }
-
- if (ngmatch(newsgroups, "sub.jokes,sub.sex,rec.humor,!rec.humor.all"))
- {
- if (askyes("Could this be offensive to anyone? ",""))
- {
- getpr("Whom might it offend? ", group);
- (void) sprintf(buf," - offensive to %s (rot 13)", group);
- modify_article(tempfname, "Subject: ", buf, APPEND);
- encode(tempfname);
- }
- }
-
- if (ngmatch(newsgroups, "sub.sources.all,!sub.sources.d,comp.sources.all,!comp.sources.wanted,!comp.sources.d,!comp.sources.bugs"))
- {
- if (!article_line(tempfname, "Subject: ", group))
- {
- nosubj:
- printf("There seems to be no subject for this article.\n");
- getpr("Subject: ", subject);
- modify_article(tempfname, "Subject: ", subject, REPLACE);
- }
- else
- {
- c = &group[8];
- while (*c == ' ' || *c == '\t')
- c++;
- if (*c == '\0')
- goto nosubj;
- strcpy(subject, c);
- }
- if (ngmatch(newsgroups, "sub.sources.d,all.wanted") || iswanted(subject))
- {
- printf("Requests for sources should not be posted to any of\n");
- printf("the comp.sources newsgroups, please post such requests\n");
- printf("to comp.sources.wanted only. Please reenter the newsgroups.\n\n");
- while (!get_newsgroup())
- ;
- modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
- }
- if (ngmatch(newsgroups, "sub.sources.all,comp.sources.all"))
- {
- if (stbuf.st_size < (4*1024))
- {
- printf("Your article seems rather small to be a source distribution.\n");
- if (!askyes("Are you certain that this is really source? ", ""))
- {
-
- while (!get_newsgroup())
- ;
- modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
- }
- }
- if (index(newsgroups, NGDELIM))
- {
- printf("Sources should be posted to one newsgroup only.\n");
- printf("Please pick the most appropriate group for your article.\n\n");
- while (!get_newsgroup())
- ;
- modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
- }
- }
- }
- if (index(newsgroups, NGDELIM) != NULL && followto[0] == '\0')
- {
- printf("Your article is being posted to multiple newsgroups.\n");
- printf("In which newsgroup should the responses be posted?\n");
- printf("Newsgroups: %s\n", newsgroups);
- printf("(If responses should be mailed to you, enter \"poster\")\n");
- getpr("Followup-To: ", followto);
- if (followto[0] != '\0')
- modify_article(tempfname, "Followup-To: ", followto,
- REPLACE);
- }
- }
-
- int iswanted(char *str)
- {
- while (*str == ' ')
- str++;
-
- if (prefix(str, "Re:"))
- return FALSE;
-
- if (isin(str, " wanted ") || isin(str, " can any") ||
- isin(str, " need ") || isin(str, " please ") || isin(str, " help ")
- || isin(str, " looking ") || index(str, '?'))
- return TRUE;
-
- return FALSE;
- }
-
- int isin(char *str, char *words)
- {
- char *p;
- int sc, wc;
-
- p = words;
- while (sc = *str++)
- {
- if ((wc = *p++) == '\0')
- return (TRUE);
- if (wc == ' ')
- {
- if (index(".,!?-; \t\n", sc))
- continue;
- }
- else
- {
- if (isupper(wc))
- wc = tolower(wc);
- if (isupper(sc))
- sc = tolower(sc);
- if (wc == sc)
- continue;
- }
- str -= p - words - 1;
- p = words;
- }
- if (*p == '\0')
- return (TRUE);
- return (FALSE);
- }
-
- /*
- * Save a copy of the article in the users NEWSARCHIVE directory.
- */
- void save_article(void)
- {
- FILE *in, *out;
- int c;
- time_t timenow, time();
- char *today, *ctime();
- struct stat stbuf;
- char filename[BUFLEN];
-
- if (stat(ccname, &stbuf) == 0 && (stbuf.st_mode&S_IFMT) == S_IFDIR)
- {
- /*
- * It would be much nicer here to write articles
- * in MH format (numbered files, in rfc822 format)
- *
- * one day ..
- */
- (void) sprintf(filename, "%s/author_copy", ccname);
- (void) strcpy(ccname, filename);
- }
- in = xfopen(tempfname, "r");
- out = xfopen(ccname, "a");
- timenow = time((time_t)0);
- today = ctime(&timenow);
- fprintf(out,"From postnews %s",today);
- while ((c=getc(in)) != EOF)
- putc(c, out);
- putc('\n', out);
- (void) fclose(in);
- (void) fclose(out);
- }
-
- /*
- * Post the article to the net.
- */
- void post_article(void)
- {
- #define TEMPOUT "T:pnews.final"
-
- FILE *fpout, *fpin, *sig;
- int status;
- int seq;
- long count;
- long pos;
-
- char buffer[LBUFLEN];
- unsigned char c;
- long t;
-
-
- printf("Posting article...\n");
- fflush(stdout);
-
- (void)time(&t);
- seq = GetSequence(1);
-
- /* Open final output file and write header */
- fpout = xfopen(TEMPOUT, "w");
-
- fprintf(fpout, "Path: %s\n", user);
- fprintf(fpout, "From: %s@%s%s (%s)\n", user, node, domain, realname);
- fprintf(fpout, "Newsgroups: %s\n", newsgroups);
- fprintf(fpout, "Subject: %s\n", subject);
- if(keywords[0] != '\0' && keywords[0] != '\n')
- fprintf(fpout, "Keywords: %s\n", keywords);
- if(summary[0] != '\0' && summary[0] != '\n')
- fprintf(fpout, "Summary: %s\n", summary);
- fprintf(fpout, "Message-ID: <%ld@%s%s>\n", seq, node, domain);
- fprintf(fpout, "Date: %s GMT\n", gettime());
- if(references[0] != '\0' && references[0] != '\n')
- fprintf(fpout, "References: %s\n", references);
- if(followto[0] != '\0' && followto[0] != '\n')
- fprintf(fpout, "Followup-To: %s\n", followto);
- if(distribution[0] != '\0')
- fprintf(fpout, "Distribution: %s\n", distribution);
- fprintf(fpout, "Organization: %s\n", organization);
- if(approved[0] != '\0')
- fprintf(fpout, "Approved: %s\n", approved);
-
-
- /* Append .signature file if available */
- fpin = xfopen(tempfname, "a");
-
- fprintf(fpin, "\n--\n");
-
- if((sig = fopen(MakeConfigPath(UULIB, ".signature"), "r")) != NULL)
- {
- while((c = getc(sig)) != EOF)
- putc(c, fpin);
- }
- else
- {
- fprintf(fpin, "signature not available yet...\n");
- }
-
- fclose(fpin);
- fclose(sig);
-
- /* Set number of lines for header entry "Lines: " */
- fpin = xfopen(tempfname, "r");
-
- /* Skip header: */
- while(fgets(buffer, sizeof(buffer), fpin))
- if(buffer[0] == '\n')
- break;
-
- count = 0;
- pos = ftell(fpin) - strlen(buffer);
-
- while(fgets(buffer, sizeof(buffer), fpin))
- count++;
-
- fprintf(fpout, "Lines: %ld\n", count);
-
- (void)fseek(fpin, pos, 0);
-
- /* Copy article to TEMPFILE */
- while((c = getc(fpin)) != EOF)
- putc(c, fpout);
-
- fclose(fpin);
- fclose(fpout);
-
- /* printf("Article will be spooled to the following system(s):\n"); */
- (void) sprintf(buf, "relaynews <%s -i", TEMPOUT);
- status = Execute(buf, 0, 0);
- /* putc('\n', stdout); */
- status = 0;
- if (status)
- {
- printf("Article not posted - exit status %d\n", status);
- return;
- } else
- printf("Article posted successfully.\n");
-
- if (ccname[0])
- {
- printf("A copy has been saved in %s\n", ccname);
- save_article();
- }
-
- (void) UNLINK(tempfname);
- (void) UNLINK(TEMPOUT);
- xxit(0);
- }
-
- char *gettime(void)
- {
- static char *wdays[] =
- {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
-
- static char *mdays[] =
- {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
-
- struct tm *tm;
- char *timestr;
- long t;
-
-
- (void)time(&t);
- tm = gmtime(&t);
-
- if((timestr = malloc(50)) == NULL)
- byebye("No mem free.");
-
- sprintf(timestr, "%s, %ld %s %ld %02ld:%02ld:%02ld",
- wdays[tm->tm_wday],
- tm->tm_mday,
- mdays[tm->tm_mon],
- tm->tm_year,
- tm->tm_hour,
- tm->tm_min,
- tm->tm_sec);
- return(timestr);
- }
-
- /*
- ** Initialization.
- */
-
- void init(void)
- {
- FILE *fd;
- int i = 0;
- char buffer[256];
-
- references[0] = '\0';
- distribution[0] = '\0';
- approved[0] = '\0';
-
- #ifdef AMIGA
- (void)getcwd(curpath, 256);
-
- newsdir = GetConfigDir(UUNEWS);
- newslibdir = MakeConfigPath(UULIB, "news");
- bugfile = MakeConfigPath(UUSPOOL, "post");
-
- activefile = malloc(strlen(newslibdir)+10);
- sprintf(activefile, "%s/active", newslibdir);
-
- user = FindConfig(USERNAME);
- realname = FindConfig(REALNAME);
- node = FindConfig(NODENAME);
- domain = FindConfig(DOMAINNAME);
- organization = FindConfig(ORGANIZATION);
- _TZ = FindConfig("TimeZone");
-
- if(user == NULL || realname == NULL || node == NULL
- || domain == NULL || organization == NULL || _TZ == NULL)
- {
- printf("Please set your enviroment\n");
- printf("Some of these variables are missing:\n");
- printf("UserName, RealName, NodeName, DomainName, Organization, TimeZone\n");
- xxit(2);
- }
- #endif
-
- tzset(); /* Set right timezone */
-
- sprintf(ccname, "%s/author_copy", newslibdir);
-
- /* pathinit(); */
-
- (void) sprintf(buf, "%s/distributions", newslibdir);
-
- fd = xfopen(buf, "r");
- for (i=0; i < MAXDISTR; i++)
- {
- /* if (fscanf(fd, "%s [%s^\n]", distr[i].abbr, distr[i].descr)
- != 2) */
-
- /* changed by -IF-. See copydists */
-
- if(fgets(buffer, sizeof(buffer)-1, fd) == NULL)
- break;
-
- copydists(buffer, distr[i].abbr, distr[i].descr);
-
- if (strcmp(distr[i].abbr, "default") == 0)
- strcpy(def_distr, distr[i--].descr);
- }
-
- fclose(fd);
- distr[i].abbr[0] = '\0';
- if (def_distr[0] == '\0')
- strcpy(def_distr, "world"); /* maybe "local" is better? */
- }
-
- /*
- * copydists - -IF- 12.05.90
- * Fuck the Lattice C *scanf routine!
- */
-
- void copydists(char *buf, char *ab, char *de)
- {
- char *ptr;
-
- ptr = buf;
-
- while(*ptr != ' ' && *ptr != '\t')
- *ab++ = *ptr++;
-
- *ab = '\0';
-
- while(*ptr == ' ' || *ptr == '\t')
- ptr++;
-
- strcpy(de, strtok(ptr, "\n\r"));
- }
-
- /*
- * Get a yes or no answer to a question. A default may be used.
- */
-
- int askyes(char *msg, char *def)
- {
- for(;;) {
- printf("%s", msg);
- buf[0] = 0;
- (void) gets(buf);
- switch(buf[0]) {
- case 'y':
- case 'Y':
- return TRUE;
- case 'n':
- case 'N':
- return FALSE;
- case '\0':
- switch(*def) {
- case 'y':
- case 'Y':
- return TRUE;
- case 'n':
- case 'N':
- return FALSE;
- }
- default:
- printf("Please answer yes or no.\n");
- }
- }
- }
-
- /*
- * Get a character string into buf, using prompt msg.
- */
- void getpr(char *msg, char *bptr)
- {
- static int numeof = 0;
- printf("%s", msg);
- (void) gets(bptr);
- (void) nstrip(bptr);
- if (feof(stdin)) {
- if (numeof++ > 3) {
- fprintf(stderr,"Too many EOFs\n");
- xxit(1);
- }
- clearerr(stdin);
- }
- }
-
- void byebye(char *mesg)
- {
- printf("%s\n", mesg);
- xxit(1);
- }
-
- /*
- * make a modification to the header of an article
- *
- * fname -- name of article
- * field -- header field to modify
- * line -- modification line
- * how -- APPEND or REPLACE
- *
- * example:
- * modify_article("/tmp/article" , "Subject:" , "new subject" , REPLACE);
- *
- *
- */
- void modify_article(char *fname, char *field, char *line, int how)
- {
- FILE *fpart, *fptmp;
- char *temp2fname = "T:post2XXXXXXXX";
- char lbfr[BUFLEN];
- int found = FALSE;
-
- MKTEMP(temp2fname);
-
- fptmp = xfopen(temp2fname, "w");
- fpart = xfopen(fname, "r");
-
- while (fgets(lbfr, BUFLEN, fpart) != NULL)
- {
- if (prefix(lbfr, field))
- {
- found = TRUE;
- (void) nstrip(lbfr);
- if (how == APPEND)
- {
- /* append to current field */
- (void) strcat(lbfr, line);
- (void) strcat(lbfr, "\n");
- }
- else
- /* replace current field */
- (void) sprintf(lbfr, "%s%s\n", field, line);
- }
- (void) fputs(lbfr, fptmp);
- }
-
- fclose(fpart);
- fclose(fptmp);
-
- fptmp = xfopen(temp2fname, "r");
- fpart = xfopen(fname, "w");
-
- if (!found)
- fprintf(fpart, "%s%s\n", field, line);
- while (fgets(buf,BUFLEN,fptmp) != NULL)
- (void) fputs(buf, fpart);
-
- (void) fclose(fpart);
- (void) fclose(fptmp);
- (void) UNLINK(temp2fname);
- }
-
-
- /* verify that newsgroup exists, and get number of entries */
- int valid_ng(char *ng, long *maxart, long *minart, char *canpost, int exact)
- {
- char ng_check[BUFLEN], ng_read[BUFLEN], *cp;
- FILE *fp;
- int found_ng;
-
- fp = xfopen(activefile, "r");
- while (fgets(ng_read, BUFLEN, fp) != NULL)
- {
- switch (sscanf(ng_read, "%s %ld %ld %c", ng_check, maxart, minart, canpost))
- {
- case 2:
- *minart = 1;
- /* fall through */
- case 3:
- *canpost = 'y';
- /* fall through */
- case 4:
- break;
-
- default:
- printf("Active file corrupt: %s", ng_read);
- byebye("Seek help!");
- }
-
- if (strcmp(ng_check, ng) == 0) {
- (void) fclose(fp);
- if (*canpost != 'n') {
- return TRUE;
- } else
- return FALSE;
- }
- }
- (void) fclose(fp);
- *maxart = 0;
- *minart = 0;
- *canpost = 'i';
- if (exact) {
- return FALSE;
- }
- if ((fp = fopen(bugfile, "r")) == NULL)
- {
- return FALSE;
- }
- found_ng = FALSE;
- while (!found_ng && fgets(ng_check, BUFLEN, fp) == ng_check) {
- if (ng_check[0] == '#')
- continue;
- cp = index(ng_check, '\n');
- *cp = '.';
- if (prefix(ng, ng_check))
- found_ng = TRUE;
- }
- (void) fclose(fp);
- if (!found_ng)
- return FALSE;
- *canpost = 'y';
- return TRUE;
- }
-
- /* get the line specified by field from an article */
- int article_line(char *article, char *field, char *line)
- {
- FILE *fp;
- char *c;
-
- fp = xfopen(article,"r");
- while ((c=fgets(line,BUFLEN,fp)) != NULL && !prefix(line, field))
- if (line[0] == '\n') {
- c = NULL;
- break;
- }
- (void) fclose(fp);
- if (c != NULL) {
- (void) nstrip(line);
- return TRUE;
- } else {
- line[0] = '\0';
- return FALSE;
- }
- }
-
- /* get the header information for a followup article */
- void followup(char *baseart)
- {
- char *p;
-
- /* subject */
- if (article_line(baseart, "Subject: ", buf))
- {
- p = buf+9;
- for ( ; ; )
- {
- while (*p == ' ' || *p == '\t')
- ++p;
- if ((*p != 'r' && *p != 'R') ||
- (p[1] != 'e' && p[1] != 'E') ||
- (p[2] != ':' && p[2] != ' '))
- break;
- p += 3;
- }
- (void) sprintf(subject, "Re: %s", p);
- }
- else
- {
- if (article_line(baseart, "From: ", buf))
- (void) sprintf(subject, "Re: orphan response from %s", buf);
- else
- (void) strcpy(subject, "Re: orphan response");
- }
-
- /* newsgroup */
- if (article_line(baseart, "Newsgroups: ", buf))
- (void) strcpy(newsgroups, buf+12);
- if (ngmatch(newsgroups, "misc.jobs.all,!misc.jobs.misc"))
- {
- printf("Your followup has been directed to misc.jobs.misc\n");
- printf("It is the proper place for followup discussions\n");
- (void) strcpy(newsgroups,"misc.jobs.misc");
- }
-
- /* distribution */
- if (article_line(baseart, "Distribution: ", buf))
- (void) strcpy(distribution, buf+14);
-
- /* references */
- if (article_line(baseart, "References: ", buf))
- {
- char *rcp;
- (void) strcpy(references, buf+12);
- (void) strcat(references, " ");
- /* keep the number of references to a reasonable number */
- rcp = rindex(references, ' '); /* Can not fail */
- while ((int)(rcp - references) > 70)
- {
- while (*--rcp != ' ')
- ;
- rcp[1] = '\0';
- }
- }
- if (article_line(baseart, "Message-ID: ", buf)) {
- (void) strcat(references, buf+12);
- (void) strcpy(msgid, buf+12);
- }
-
- if (article_line(baseart, "From: ", buf))
- (void) strcpy(isfrom, buf+6);
-
- if (article_line(baseart, "Keywords: ", buf))
- (void) strcpy(keywords, buf+10);
-
- if (article_line(baseart, "Followup-To: ", buf))
- {
- (void) strcpy(newsgroups, buf+13);
- if (strcmp(newsgroups, "poster") == 0)
- byebye("Mail followups directly to poster.");
- }
- get_summary();
- }
-
- void get_summary(void)
- {
- char *p;
- int i;
-
- printf("Please enter a short summary of your contribution to the discussion\n");
- printf("Just one or two lines ... (end with a blank line)\n");
- p = summary;
- for (i = 0; i < 3; i++) { /* 3 * 80 < 256, should be safe .. */
- getpr(">\t", p);
- if (*p == '\0')
- break;
- p = index(p, '\0');
- (void) strcpy(p, "\n\t ");
- p += 3;
- }
- if (p > summary)
- p[-3] = '\0';
- }
-
- void encode(char *article)
- {
- FILE *fpart, *fphead, *fpcoded;
- char *headerfile = "T:pheadXXXXXXXX";
- char *codedfile = "T:pcodeXXXXXXXX";
-
- MKTEMP(headerfile);
- MKTEMP(codedfile);
-
- fpart = xfopen(article, "r");
-
- /* place article header in "headerfile" file */
- fphead = xfopen(headerfile, "w");
- while (fgets(buf, BUFLEN, fpart) != NULL)
- {
- (void) fputs(buf, fphead);
- if (buf[0] == '\n')
- break;
- }
- (void) fclose(fphead);
-
- /* place article body in "codedfile" file */
- fpcoded = xfopen(codedfile, "w");
- while (fgets(buf, BUFLEN, fpart) != NULL)
- (void) fputs(buf, fpcoded);
- (void) fclose(fpcoded);
- (void) fclose(fpart);
-
- /* encode body and put back together with header */
- (void) rename(headerfile, article);
-
- (void) sprintf(buf,"%s <%s >>%s 13\n", "caesar", codedfile, article);
- printf("Encoding article -- please stand by\n");
- (void) fflush(stdout);
- /*
- if (Execute(buf, NULL, NULL)) {
- printf("encoding failed");
- xxit(2);
- }
- */
- Execute(buf, NULL, NULL);
- (void) UNLINK(codedfile);
- }
-
-
- /*
- * Print a recorded message warning the poor luser what he is doing
- * and demand that he understands it before proceeding. Only do
- * this for newsgroups listed in LIBDIR/recording.
- */
-
- int recording(char *ngrps)
- {
- char recbuf[BUFLEN];
- FILE *fd;
- char nglist[BUFLEN], fname[BUFLEN];
- int c, n, yes, retval = 0;
-
- (void) sprintf(recbuf, "%s/recording", newslibdir);
- fd = fopen(recbuf, "r");
- if (fd == NULL)
- return 0;
- while ((fgets(recbuf, sizeof recbuf, fd)) != NULL)
- {
- (void) sscanf(recbuf, "%s %s", nglist, fname);
- if (ngmatch(ngrps, nglist))
- {
- (void) fclose(fd);
- if (fname[0] == '/')
- (void) strcpy(recbuf, fname);
- else
- (void) sprintf(recbuf, "%s/%s", newslibdir, fname);
- fd = fopen(recbuf, "r");
- if (fd == NULL)
- return 0;
- while ((c = getc(fd)) != EOF)
- putc(c, stderr);
- fclose(fd);
- fprintf(stderr, "Do you understand this? Hit <return> to proceed, <BREAK> to abort: ");
- fflush(stderr);
- n = read(0, recbuf, 100);
- c = recbuf[0];
- yes = (c=='y' || c=='Y' || c=='\n' || c=='\n' || c==0);
- if (n <= 0 || !yes)
- retval = -1;
- }
- }
- return retval;
- }
-
- void xxit(int i)
- {
- #ifdef SERVER
- (void) UNLINK(original);
- (void) UNLINK(active_name());
- #endif /* SERVER */
- exit(i);
- chdir(curpath);
- }
-
-
- /************** funcs.c ***********/
-
- /*
- * This software is Copyright 1986, 1989 by Rick Adams.
- *
- * Permission is hereby granted to copy, reproduce, redistribute or
- * otherwise use this software as long as: there is no monetary
- * profit gained specifically from the use or reproduction or this
- * software, it is not sold, rented, traded or otherwise marketed, and
- * this copyright notice is included prominently in any copy
- * made.
- *
- * The author make no claims as to the fitness or correctness of
- * this software for any use whatsoever, and it is provided as is.
- * Any use of this software is at the user's own risk.
- *
- * funcs - functions used by many programs
- */
-
-
- /*
- * News group matching.
- *
- * nglist is a list of newsgroups.
- * sublist is a list of subscriptions.
- * sublist may have "meta newsgroups" in it.
- * All fields are NGDELIM separated,
- * and there is an NGDELIM at the end of each argument.
- *
- * Currently implemented glitches:
- * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
- * If subscription X matches Y, it also matches Y.anything.
- */
-
- int ngmatch(char *nglist, char *sublist)
- {
- char *n, *s;
- int rc;
-
- rc = FALSE;
- for (n = nglist; *n != '\0' && rc == FALSE;)
- {
- for (s = sublist; *s != '\0';)
- {
- if (*s != NEGCHAR)
- rc = rc || ptrncmp(s, n);
- else
- rc = rc && !ptrncmp(s+1, n);
- while (*s++ != NGDELIM && *s != '\0')
- ;
- }
- while (*n++ != NGDELIM && *n != '\0')
- ;
- }
- return rc;
- }
-
- /*
- * Compare two newsgroups for equality.
- * The first one may be a "meta" newsgroup.
- */
- int ptrncmp(char *ng1, char *ng2)
- {
- while (*ng1 != NGDELIM && *ng1 != '\0')
- {
- if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l')
- {
- ng1 += 3;
- while (*ng2 != NGDELIM && *ng2 != '.' && *ng2 != '\0')
- if (ptrncmp(ng1, ng2++))
- return(TRUE);
- return ptrncmp(ng1, ng2);
- } else if (*ng1++ != *ng2++)
- return FALSE;
- }
- return *ng2 == '.' || *ng2 == NGDELIM || *ng2 == '\0';
- }
-
-
- /*
- * Strip trailing newlines, blanks, and tabs from 's'.
- * Return TRUE if newline was found, else FALSE.
- */
- int nstrip(char *s)
- {
- char *p;
- int rc;
-
- rc = FALSE;
- p = s;
- while (*p)
- if (*p++ == '\n')
- rc = TRUE;
- while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
- *++p = '\0';
- return rc;
- }
-
- /*
- * Local open routine.
- */
- FILE *xfopen(name, fmode)
- char *name, *fmode;
- {
- FILE *fp;
-
- if ((fp = fopen(name, fmode)) == NULL) {
- xerror("Cannot open %s (%s)", name, fmode, 0);
- }
- return fp;
- }
-
-
- /* From UC Berkeley @(#)strcasecmp.c 1.3 (Berkeley) 8/3/87 */
-
- /*
- * This array is designed for mapping upper and lower case letter
- * together for a case independent comparison. The mappings are
- * based upon ascii character sequences.
- */
-
- char charmap[] =
- {
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
- };
-
- int prefix(char *full, char *pref)
- {
- char *cm = charmap;
-
- while (*pref != '\0') {
- if (cm[*full++] != cm[*pref++])
- return FALSE;
- }
- return TRUE;
- }
-
-
- /*
- * Return TRUE iff ngname is a valid newsgroup name
- */
- int validng(char *ngname)
- {
- FILE *fp;
- char *p, *q;
- char abuf[BUFLEN];
-
- fp = xfopen(activefile, "r");
- while(fgets(abuf, BUFLEN, fp) != NULL)
- {
- p = abuf;
- q = ngname;
- while (*p++ == *q++)
- ;
- if (*--q == '\0' && *--p == ' ')
- {
- (void) fclose(fp);
- return TRUE;
- }
- }
- (void) fclose(fp);
- return FALSE;
- }
-