Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!usc!brutus.cs.uiuc.edu!samsung!munnari.oz.au!basser!ultima!nick From: nick@ultima.cs.uts.oz (Nick Andrew) Newsgroups: comp.os.minix Subject: News for Minix (part 8 of 12) Keywords: news Message-ID: <16750@ultima.cs.uts.oz> Date: 7 Dec 89 11:53:59 GMT Organization: Comp Sci, NSWIT, Australia Lines: 2284 #! /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 'rfuncs2.c' <<'END_OF_FILE' X/* X * This software is Copyright 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 * rfuncs2 - more routines needed by readr. X */ X X#ifdef SCCSID Xstatic char *SccsId = "@(#)rfuncs2.c 1.35 3/21/87"; X#endif /* SCCSID */ X X/*LINTLIBRARY*/ X X#include "rparams.h" X Xstatic char lbuf[LBUFLEN]; Xextern char *replyname(); X XFILE *popen(); X X/* X * Match title. X */ Xtitmat(h, titlist) Xregister struct hbuf *h; Xregister char *titlist; X{ X register char *p; X X while (*titlist != '\0') { X X if (strcmp(titlist, h->ident) == 0) X return TRUE; X for (p = h->title; *p != '\0'; p++) X if (prefix(p, titlist)) { X return TRUE; X } X while (*titlist++ != '\0') X ; X } X return FALSE; X} X X X/* X * Save the news item in the user's file. X * Allow files with first character as '|' to write article X * to program across a pipe. X */ X X#define PIPECHAR '|' X Xsave(file, to) Xregister char *file, *to; X{ X register FILE *ufp, *hfp; X#ifdef u370 X static struct hbuf hh; X#else /* !u370 */ X struct hbuf hh; X#endif /* !u370 */ X int isprogram = 0; X int isnew = 1; X register int i; X X for(i=0;i', ofp); X (void) fputs(bfr, ofp); X if (ferror(ofp)) break; /* E.g. disk full */ X } X if (SigTrap) X qfflush(ofp); X (void) fflush(ofp); X fprintf(ofp, (SigTrap ? "\n\n" : "\n")); X SigTrap = FALSE; X} X X X/* X * Print the file header. X */ Xhprint(hp, ofp, verbose) Xregister struct hbuf *hp; Xint verbose; Xregister FILE *ofp; X{ X register char *p1, *p2; X char fname[BUFLEN]; X char *tailpath(); X X fname[0] = '\0'; /* init name holder */ X X if (verbose == 2) { X lhwrite(hp, ofp); X return; X } X X if (lflag || eflag) { X char buf1[80], buf2[200]; X char *cp; X X (void) strcpy(bfr, groupdir); X for (cp=bfr; *cp; cp++) X if (*cp == '/') X *cp = '.'; X (void) sprintf(buf1, "%s/%ld", bfr, bit); X (void) sprintf(buf2, "%-20s %s", buf1, hp->title); X fprintf(ofp, "%.76s\n", buf2); X return; X } X X p1 = index(hp->from, '('); /* Find the sender's full name. */ X if (p1 == NULL && hp->path[0]) X p1 = index(hp->path, '('); X if (p1 != NULL) { X strcpy(fname, p1+1); X p2 = index(fname, ')'); X if (p2 != NULL) X *p2 = '\0'; X } X X fprintf(ofp, "Subject: %s\n", hp->title); X if (!hflag && hp->summary[0]) X fprintf(ofp, "Summary: %s\n", hp->summary); X if (!hflag && hp->keywords[0]) X fprintf(ofp, "Keywords: %s\n", hp->keywords); X if (verbose) { X fprintf(ofp, "From: %s\n", hp->from); X fprintf(ofp, "Path: %s\n", hp->path); X if (hp->organization[0]) X fprintf(ofp, "Organization: %s\n", hp->organization); X } X else { X if (p1 != NULL) X *--p1 = '\0'; /* bump over the '(' */ X#ifdef INTERNET X /* X * Prefer Path line if it's in internet format, or if we don't X * understand internet format here, or if there is no reply-to. X */ X fprintf(ofp, "From: %s", hp->from); X#else X fprintf(ofp, "Path: %s", tailpath(hp)); X#endif X if (fname[0] || hp->organization[0]) { X if (fname[0] == '\0') { X (void) strcpy(fname,hp->from); X p2 = index(fname,'@'); X if (p2) X *p2 = '\0'; X } X fprintf(ofp, " (%s", fname); X if (hp->organization[0] && !hflag) X fprintf(ofp, " @ %s", hp->organization); X fprintf(ofp, ")"); X } X fprintf(ofp, "\n"); X if (p1 != NULL) X *p1 = ' '; X } X X if (verbose) { X fprintf(ofp, "Newsgroups: %s\n", hp->nbuf); X fprintf(ofp, "Date: %s\n", hp->subdate); X if (hp->sender[0]) X fprintf(ofp, "Sender: %s\n", hp->sender); X if (hp->replyto[0]) X fprintf(ofp, "Reply-To: %s\n", hp->replyto); X if (hp->followto[0]) X fprintf(ofp, "Followup-To: %s\n", hp->followto); X } X else if (index(hp->nbuf, ',') || strcmp(groupdir, "junk") == 0) X fprintf(ofp, "Newsgroups: %s\n", hp->nbuf); X X if (pflag || ofp != stdout) X putc('\n', ofp); X} X X X/* X * If ofp != stdout, close it and run the script in coptbuf. X */ Xcout(ofp) XFILE *ofp; X{ X register char *p, *q, *r; X X if (ofp == stdout || ofp == NULL) X return; X (void) fclose(ofp); X p = coptbuf; X q = lbuf; X while ((*q = *p++) != '\0') X if (*q++ == FMETA) { X q--; X r = outfile; X while ((*q++ = *r++) != '\0') X ; X q--; X } X fwait(fsubr(ushell, lbuf, (char *)NULL)); X (void) unlink(outfile); X} X X Xcdump(ofp) Xregister FILE *ofp; X{ X if (ofp == stdout) X return; X fclose(ofp); X unlink(outfile); X} X X X/* X * Quiet 'flush'. X * Empty (without fflush()) the buffer for stream fp. X */ X/* ARGSUSED */ Xqfflush(fp) XFILE *fp; X{ X#ifdef fileno X int fno, err; X X fno = fileno(fp); X err = ferror(fp); X fileno(fp) = -1; X (void) fflush(fp); X fileno(fp) = fno; X if (!err) X (void) clearerr(fp); X#endif /* fileno */ X} X X/* X * Count the number of remaining lines in file fp. X * Do not move the file pointer. X */ Xlinecnt(fp) XFILE *fp; X{ X long curpos; X register int nlines = 0; X register int c; X X if (fp == NULL) X return 0; X curpos = ftell(fp); X while ((c = getc(fp)) != EOF) X if (c == '\n') X nlines++; X (void) fseek(fp, curpos, 0); X return nlines; X} X X X/* X * Transmit file to system. X */ Xtransmit(sp, file) Xregister struct srec *sp; Xchar *file; X{ X register FILE *ifp, *ofp; X register int c, i; X#ifdef u370 X static struct hbuf hh; X#else /* !u370 */ X struct hbuf hh; X#endif /* !u370 */ X char TRANS[BUFLEN]; X X#ifdef DEBUG X fprintf(stderr, "xmit %s to %s using %s\n", file, sp->s_name, sp->s_xmit); X#endif X bzero((char *)&hh, sizeof hh); X ifp = xart_open(file, "r"); X if (hread(&hh, ifp, TRUE) == NULL) X return; X strcpy(TRANS, "/tmp/trXXXXXX"); X ofp = xfopen(mktemp(TRANS), "w"); X if (index(sp->s_flags, 'A') == NULL) X hwrite(&hh, ofp); X else { X#ifdef OLD X fprintf(ofp, "A%s\n%s\n%s!%s\n%s\n%s\n", oident(hh.ident), hh.nbuf, PATHSYSNAME, X hh.path, hh.subdate, hh.title); X#else /* !OLD */ X logerr("Must have OLD defined to use A flag for xmit"); X unlink(TRANS); X return; X#endif /* !OLD */ X } X while ((c = getc(ifp)) != EOF) X putc(c, ofp); X (void) fclose(ifp); X (void) fclose(ofp); X for (i=0;is_xmit == '\0' || strpbrk(sp->s_flags, "FUMH")) X (void) sprintf(bfr, DFTXMIT, sp->s_name, TRANS); X else X (void) sprintf(bfr, "(%s) < %s", sp->s_xmit, TRANS); X#ifdef DEBUG X fprintf(stderr, "%s\n", bfr); X#endif X (void) system(bfr); X (void) unlink(TRANS); X} X X X/* X * Cancel the article whose header is in hp, by posting a control message X * to cancel it. The scope of the control message depends on who would X * really be willing to cancel it. It is sent as far as it will do any good. X * notauthor is true iff the person posting this article is not the X * real author of the article being cancelled. X */ Xcancel(ofp, hp, notauthor) XFILE *ofp; Xstruct hbuf *hp; Xint notauthor; X{ X int pid; X X fflush(ofp); X pid = vfork(); X if (pid < 0) { X perror("readnews: cancel"); X return 0; X } X if (pid > 0) X return 0; X if (notauthor) X (void) sprintf(bfr, "%s/%s -c 'cancel %s' -n %s -d %s < /dev/null", X LIB, "inews", hp->ident, hp->nbuf, X#ifdef ORGDISTRIB X ORGDISTRIB); X#else /* !ORGDISTRIB */ X "local"); X#endif /* !ORGDISTRIB */ X else { X if (hp->distribution[0] == '\0') X (void) sprintf(bfr, "%s/%s -c 'cancel %s' -n %s < /dev/null", X LIB, "inews", hp->ident, hp->nbuf); X else X (void) sprintf(bfr, "%s/%s -c 'cancel %s' -n %s -d %s < /dev/null", X LIB, "inews", hp->ident, hp->nbuf, hp->distribution); X } X execl("/bin/sh", "sh", "-c", bfr, (char *) 0); X perror(bfr); X for ( ; ; ) X exit(1); X} X X Xdash(num, ofp) Xregister int num; Xregister FILE *ofp; X{ X register int i; X X for (i = 0; i < num; i++) X putc('-', ofp); X putc('\n', ofp); X} X X Xhelp(ofp) Xregister FILE *ofp; X{ X register FILE *fp; X register int c; X char temp[BUFLEN]; X X if (cflag) { Xoneline: X fprintf(ofp, "(n)ext re(p)rint (w)rite (q)uit (r)eply\ X (c)ancel -[n] +[n] (f)ollowup (N)ext (U)nsubscribe (v)ersion\n"); X return; X } X (void) sprintf(temp, "%s/%s", LIB, "help"); X if ((fp = fopen(temp, "r")) == NULL) { X fprintf(ofp, "No help file.\n"); X goto oneline; X } X while ((c = getc(fp)) != EOF && !SigTrap) X putc(c, ofp); X (void) fclose(fp); X} X X Xpout(ofp) XFILE *ofp; X{ X register char *p, *q, *r; X X p = PAGER; X q = lbuf; X while ((*q = *p++) != '\0') X if (*q++ == FMETA) { X q--; X r = filename; X while ((*q++ = *r++) != '\0') X ; X q--; X } X fwait(fsubr(ushell, lbuf, (char *)NULL)); X fprintf(ofp, "\n"); X} X X/* X * Print a very brief version of the date in question. X */ Xchar * Xbriefdate(datestr) Xchar *datestr; X{ X time_t dt, now; X char *tmstr; X char *wkday, *monthdate, *timeofday; X static char rbuf[20]; X X dt = cgtdate(datestr); X tmstr = ctime(&dt); X X wkday = tmstr; tmstr[3] = '\0'; X monthdate = tmstr+4; tmstr[10] = '\0'; X timeofday = tmstr+11; tmstr[16] = '\0'; X X (void) time(&now); X if (now - dt < WEEKS) X (void) strcpy(rbuf, wkday); X else X (void) strcpy(rbuf, monthdate); X (void) strcat(rbuf, " "); X (void) strcat(rbuf, timeofday); X return rbuf; X} X X/* X * Return TRUE iff stdout is /dev/null. X */ Xignoring() X{ X struct stat ss, ns; X X if (fstat(1, &ss) < 0) X return FALSE; X if (stat("/dev/null", &ns) < 0) X return FALSE; X if (ss.st_dev == ns.st_dev && ss.st_rdev == ns.st_rdev) X return TRUE; X return FALSE; X} END_OF_FILE if test 11135 -ne `wc -c <'rfuncs2.c'`; then echo shar: \"'rfuncs2.c'\" unpacked with wrong size! fi # end of 'rfuncs2.c' fi if test -f 'pathinit.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pathinit.c'\" else echo shar: Extracting \"'pathinit.c'\" \(10623 characters\) sed "s/^X//" >'pathinit.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 * This function initializes all the strings used for the various X * filenames. They cannot be compiled into the program, since that X * would be non-portable. With this convention, the netnews sub-system X * can be owned by any non-privileged user. It is also possible X * to work when the administration randomly moves users from one X * filesystem to another. The convention is that a particular user X * (HOME, see Makefile) is searched for in /etc/passwd and all files X * are presumed relative to there. This method also allows one copy X * of the object code to be used on ANY machine. (this code runs X * un-modified on 50+ machines at IH!!) X * X * The disadvantage to using this method is that all netnews programs X * (inews, readnews, rnews, checknews) must first search /etc/passwd X * before they can start up. This can cause significant overhead if X * you have a big password file. X * X * Some games are played with ifdefs to get four .o files out of this X * one source file. INEW is defined for inews, READ for readnews, X * CHKN for checknews, and EXP for expire. X */ X X#ifdef SCCSID Xstatic char *SccsId = "@(#)pathinit.c 1.23 4/6/87"; X#endif /* SCCSID */ X X#if defined(INEW) || defined(EXP) X#include "iparams.h" X#endif /* INEW || EXP */ X X#ifdef READ X#include "rparams.h" X#endif /* READ */ X X#if defined(CHKN) X#include "params.h" X#endif /* CHKN */ X X Xchar *FROMSYSNAME, *PATHSYSNAME, *LOCALSYSNAME, *LOCALPATHSYSNAME; Xchar *SPOOL, *LIB, *BIN, *ACTIVE, *SUBFILE, *ARTFILE, X *username, *userhome; X X#ifdef INEW Xchar *LOCKFILE, *SEQFILE, *ARTICLE, *INFILE, *TELLME; X Xint c_cancel(), c_newgroup(), c_ihave(), c_sendme(), c_rmgroup(), X c_sendsys(), c_version(), c_checkgroups(), c_unimp(); X Xstruct msgtype msgtype[] = { X "cancel", NULL, c_cancel, X "newgroup", NULL, c_newgroup, X "ihave", NULL, c_ihave, X "sendme", NULL, c_sendme, X "sendbad", NULL, c_sendme, X "rmgroup", NULL, c_rmgroup, X "sendsys", NULL, c_sendsys, X "version", NULL, c_version, X "checkgroups", NULL, c_checkgroups, X "delsub", NULL, c_unimp, X NULL, NULL, NULL X}; X#endif /* INEW */ X X#if defined(INEW) || defined(READ) Xchar *ALIASES; X#endif /* INEW || READ */ X X#ifdef EXP Xchar *OLDNEWS; X#endif /* EXP */ X X#ifdef READ Xchar *MAILPARSER; X#endif /* READ */ X X Xstruct passwd *getpwnam(); Xchar *rindex(); X X#define Sprintf(where,fmt,arg) (void) sprintf(bfr,fmt,arg); where = AllocCpy(bfr) X Xchar * XAllocCpy(cp) Xregister char *cp; X{ X register char *mp; X char *malloc(); X X mp = malloc((unsigned)strlen(cp) + 1); X X if (mp == NULL) X xerror("malloc failed on %s", cp); X X (void) strcpy(mp, cp); X return mp; X} X Xpathinit() X{ X#ifndef ROOTID X struct passwd *pw; /* struct for pw lookup */ X#endif /* !ROOTID */ X#ifdef EXP X char *p; X#endif /* EXP */ X#ifndef CHKN X struct utsname ubuf; X char buf[BUFLEN]; X extern char *mydomain(); X X uname(&ubuf); X X#ifdef HIDDENNET_IN_LOCALSYSNAME X /* old compatibility code, remove when HIDDENNET is used no more */ X if (strcmp(ubuf.nodename, HIDDENNET) != 0) X (void) sprintf(buf, "%s.%s%s", ubuf.nodename, HIDDENNET, X mydomain()); X else X#endif X (void) sprintf(buf, "%s%s", ubuf.nodename, mydomain()); X LOCALSYSNAME = AllocCpy(buf); X X#ifdef GENERICFROM X (void) sprintf(buf, GENERICFROM, ubuf.nodename, mydomain()); X FROMSYSNAME = AllocCpy(buf); X#else /* !GENERICFROM */ X FROMSYSNAME = LOCALSYSNAME; X#endif /* !GENERICFROM */ X X LOCALPATHSYSNAME = AllocCpy(ubuf.nodename); X X#ifdef GENERICPATH X (void) sprintf(buf, GENERICPATH, ubuf.nodename, mydomain()); X PATHSYSNAME = AllocCpy(buf); X#else /* !GENERICPATH */ X PATHSYSNAME = LOCALPATHSYSNAME; X#endif /* !GENERICPATH */ X X#endif /* !CHKN */ X X#ifdef HOME X /* Relative to the home directory of user HOME */ X (void) sprintf(bfr, "%s/%s", logdir(HOME), SPOOLDIR); X SPOOL = AllocCpy(bfr); X (void) sprintf(bfr, "%s/%s", logdir(HOME), LIBDIR); X LIB = AllocCpy(bfr); X#else /* !HOME */ X /* Fixed paths defined in Makefile */ X SPOOL = AllocCpy(SPOOLDIR); X LIB = AllocCpy(LIBDIR); X#endif /* !HOME */ X X#ifdef IHCC X (void) sprintf(bfr, "%s/%s", logdir(HOME), BINDIR); X BIN = AllocCpy(bfr); X#else /* !IHCC */ X Sprintf(BIN, "%s", BINDIR); X#endif /* !IHCC */ X X Sprintf(ACTIVE, "%s/active", LIB); X X#ifdef EXP X (void) strcpy(bfr, SPOOL); X p = rindex(bfr, '/'); X if (p) { X strcpy(++p, "oldnews"); X OLDNEWS = AllocCpy(bfr); X } else X OLDNEWS = AllocCpy("oldnews"); X#endif /* EXP */ X X#ifndef CHKN X Sprintf(SUBFILE, "%s/sys", LIB); X Sprintf(ARTFILE, "%s/history", LIB); X# endif /* !CHKN */ X X# ifdef READ X#ifdef SENDMAIL X Sprintf(MAILPARSER, "%s -oi -oem", SENDMAIL); X#else /* !SENDMAIL */ X Sprintf(MAILPARSER, "%s/recmail", LIB); X#endif /* !SENDMAIL */ X# endif /* READ */ X X# if defined(READ) || defined(INEW) X Sprintf(ALIASES, "%s/aliases", LIB); X# endif /* READ || INEW */ X# ifdef INEW X Sprintf(LOCKFILE, "%s/LOCK", LIB); X Sprintf(SEQFILE, "%s/seq", LIB); X Sprintf(ARTICLE, "%s/.arXXXXXX", SPOOL); X Sprintf(INFILE, "%s/.inXXXXXX", SPOOL); X/* X * The person notified by the netnews sub-system. Again, no name is X * compiled in, but instead the information is taken from a file. X * If the file does not exist, a "default" person will get the mail. X * If the file exists, but is empty, nobody will get the mail. This X * may seem backwards, but is a better fail-safe. X */ X# ifdef NOTIFY X parse_notify(); X# endif /* NOTIFY */ X X/* X * Since the netnews owner's id number is different on different X * systems, we'll extract it from the /etc/passwd file. If no entry, X * default to root. This id number seems to only be used to control who X * can input certain control messages or cancel any message. Note that X * entry is the name from the "notify" file as found above if possible. X * Defining ROOTID in defs.h hardwires in a number and avoids X * another search of /etc/passwd. X */ X# ifndef ROOTID X if ((pw = getpwnam(TELLME)) != NULL) X ROOTID = pw->pw_uid; X else if ((pw = getpwnam(HOME)) != NULL) X ROOTID = pw->pw_uid; X else X ROOTID = 0; /* nobody left, let only root */ X# endif /* !ROOTID */ X#endif /* INEW */ X} X X#ifdef INEW X#ifdef NOTIFY X/* X * Attempt to parse the LIB/notify file into the global structure msgtype[]. X */ Xparse_notify() X{ X FILE *nfd; X int valid = 0, done = 0; X register struct msgtype *mp; X char mtype[BUFLEN], addr[BUFLEN]; X X (void) sprintf(bfr, "%s/notify", LIB); X#ifndef ROOTID X TELLME = AllocCpy(NOTIFY); X#endif /* !ROOTID */ X if ( (nfd = fopen(bfr, "r")) == NULL) { X /* X * Set defaults to NOTIFY X */ X#ifdef debug X log("parse_notify: %s/notify not found", LIB); X#endif /* debug */ X (void)setmsg("all", NOTIFY); X return; X } X do { X mtype[0] = addr[0] = 0; X switch( get_notify(nfd, mtype, addr) ) { X case 0: X continue; X case 1: X valid += setmsg(mtype, ""); X break; X case 2: X valid += setmsg(mtype, addr); X break; X case -1: X if( !valid ) { X#ifdef debug X log("parse_notify: no valid entries found."); X#endif /* debug */ X setmsg("all", ""); /* send mail to no one */ X } X done = 1; X } X } while( !done ); X X /* X * point to zero length string for all entries we haven't touched X */ X for(mp=msgtype; mp->m_name; mp++) X if(mp->m_who_to == 0) X mp->m_who_to = ""; X} X Xsetmsg(what, to) Xchar *what, *to; X{ X register struct msgtype *mp; X#ifdef debug X log("setmsg: what='%s', to='%s'", what, to); X#endif /* debug */ X /* X * Special case for "all" X */ X if(strcmp(what, "all") == 0) { X for(mp=msgtype; mp->m_name; mp++) { X mp->m_who_to = AllocCpy(to); X#ifdef debug X log("setmsg: '%s'='%s'", mp->m_name, mp->m_who_to); X#endif /* debug */ X } X return 1; X } X X for(mp=msgtype; mp->m_name; mp++) X if(strcmp(mp->m_name, what) == 0) { X mp->m_who_to = AllocCpy(to); X#ifdef debug X log("setmsg: '%s'='%s'", mp->m_name, mp->m_who_to); X#endif /* debug */ X return 1; X } X return 0; X} X Xstatic Xget_notify(fp, s, t) XFILE *fp; Xregister char *s, *t; X{ X register char *cp; X char pbuf[BUFSIZ]; X X if( cp=fgets(pbuf, sizeof(pbuf), fp ) ) { X if( *cp == '\n' ) X return 0; X while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n') X *s++ = *cp++; X *s = '\0'; /* terminate first string */ X X while(*cp && (*cp == ' ' || *cp == '\t' || *cp == '\n') ) X cp++; /* look for start of second */ X if( !*cp || *cp == '\n' ) X return 1; /* no second string */ X X while( *cp && *cp != '\n' ) X *t++ = *cp++; X *t = '\0'; X return 2; X } else X return -1; X} X#endif /* NOTIFY */ X#endif /* INEW */ X X#ifndef CHKN X/* X * At sites where the are many mail domains within the support area of a single X * news administrator, it is much nicer to be able to read the local domain of X * a machine from a file. What we do here is: X * 1) Check for the presence of a LIBDIR/localdomain file. If it doesn't X * exist,assume that MYDOMAIN should be used instead. X * 2) If it does exist, we make the following assumptions: X * a) If it is empty, has only comments, or only blank lines; we assume X * the domain is desired to be a zero length string ( ie ""). (this X * implies that the domain name is contained in the hostname.) X * b) If it is not empty, we assume the first line not beginning with a X * '#', blank/tab, or newline is the desired domain name. X * A like '.UUCP' or '.TEK.COM' should be used. We could insure that X * the line begin with a '.' to be a valid domain name, but I don't X * think it is necessary to put that restriction on it. X */ Xchar * Xmydomain() X{ X static char *md = NULL; X register char *cp; X FILE *fp = NULL; X char fbuf[BUFLEN]; X extern char *malloc(), *strcpy(), *index(); X X if(md) /* we've been here before, so just return what we found */ X return(md); X X (void) sprintf(fbuf,"%s/localdomain", LIBDIR); X if ( (fp = fopen(fbuf,"r")) == NULL) { X md = MYDOMAIN; /* No localdomain file, use MYDOMAIN instead */ X } else { X while(fgets(fbuf, sizeof(fbuf), fp) ) { X if( *fbuf == '\n' || *fbuf == '#' X || *fbuf == ' ' || *fbuf == '\t') X continue; X X if( cp = index(fbuf, '\n') ) X *cp = '\0'; X X if ( (md = malloc(strlen(fbuf) + 1)) == NULL) X md = MYDOMAIN; /* punt here */ X else X (void)strcpy(md, fbuf); X break; X } X } X X if(fp) X (void)fclose(fp); X X if( md == NULL) X md = ""; X X return md; X} X#endif /* !CHKN */ END_OF_FILE if test 10623 -ne `wc -c <'pathinit.c'`; then echo shar: \"'pathinit.c'\" unpacked with wrong size! fi # end of 'pathinit.c' fi if test -f 'checknews.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'checknews.c'\" else echo shar: Extracting \"'checknews.c'\" \(11026 characters\) sed "s/^X//" >'checknews.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 * checknews - news checking program X */ X X#ifdef SCCSID Xstatic char *SccsId = "@(#)checknews.c 2.29 4/6/87"; X#endif /* SCCSID */ X Xchar *Progname = "checknews"; /* used by xerror */ X X#include "params.h" X Xchar optbuf[BUFLEN]; /* NEWSOPTS buffer */ Xint y, e, n, q; Xint verbose; /* For debugging. */ Xint nflag; /* for spec. newsgroup */ Xchar narggrp[BUFLEN]; /* spec newsgroup */ X X#ifdef MINIX X/* make 'em external */ Xextern char bfr[LBUFLEN]; /* general-use scratch area */ Xextern char newsrc[],*rcline[],rcbuf[],*argvrc[]; Xextern FILE *rcfp, *actfp; X#else Xchar bfr[LBUFLEN]; /* general-use scratch area */ Xchar newsrc[BUFLEN],*rcline[LINES],rcbuf[LBUFLEN],*argvrc[LINES]; XFILE *rcfp, *actfp; X#endif X Xint mode = 1; Xextern int line; X X X#ifndef SHELL X#ifdef MINIX X/* Make it extern */ Xextern X#endif X Xchar *SHELL; X#endif X Xmain(argc, argv) Xint argc; Xregister char **argv; X{ X register char *ptr; /* pointer to rest of buffer */ X char *user, *home; X struct passwd *pw; X struct group *gp; X int sflag = 0, optflag = FALSE, space = FALSE; X int i; X X y = 0; X n = 0; X e = 0; X q = 0; X nflag = 0; X pathinit(); X if (--argc > 0) { X for (argv++; **argv; ++*argv) { X switch(**argv) { X case 'y': X y++; X break; X case 'q': X q++; X break; X case 'v': X verbose++; X break; X case 'n': X n++; X break; X case 'N': X nflag++; X if (argc <= 1) X xerror("No newsgroup specified with -N"); X strcpy(narggrp,argv[1]); X strcat(narggrp,","); X break; X case 'e': X case 'f': X e++; X break; X } X } X } X if (!n && !e && !y && !q) X y++; X if (nflag) X argv++; X X#ifndef V6 X if ((user = getenv("USER")) == NULL) X user = getenv("LOGNAME"); X if ((home = getenv("HOME")) == NULL) X home = getenv("LOGDIR"); X if (user == NULL || home == NULL) X getuser(); X else { X username = AllocCpy(user); X userhome = AllocCpy(home); X } X if (ptr = getenv("NEWSOPTS")) X strcpy(rcbuf, ptr); X else X *rcbuf = '\0'; X if (*rcbuf) { X strcat(rcbuf, " \1"); X ptr = rcbuf; X while (*++ptr) X if (isspace(*ptr)) X *ptr = '\0'; X for (ptr = rcbuf;; ptr++) { X if (!*ptr) X continue; X if (*ptr == '\1') X break; X if (++line > LINES) X xerror("Too many options."); X if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL) X xerror("Not enough memory."); X argvrc[line] = rcline[line]; X strcpy(rcline[line], ptr); X while (*ptr) X ptr++; X } X } X#else X getuser(); X#endif X ptr = getenv("NEWSRC"); X if (ptr == NULL) X sprintf(newsrc, "%s/%s", userhome, NEWSRC); X else X strcpy(newsrc, ptr); X if ((rcfp = fopen(newsrc, "r")) != NULL) { X while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) { X if (!(space = isspace(*rcbuf))) X optflag = FALSE; X if (!strncmp(rcbuf, "options ", 8)) X optflag = TRUE; X if (optflag) { X strcat(rcbuf, "\1"); X if (space) X ptr = rcbuf - 1; X else X ptr = &rcbuf[7]; X while (*++ptr) X if (isspace(*ptr)) X *ptr = '\0'; X if (space) X ptr = rcbuf; X else X ptr = &rcbuf[8]; X for (;; ptr++) { X if (!*ptr) X continue; X if (*ptr == '\1') X break; X if (++line > LINES) X xerror("Too many options."); X if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL) X xerror("Not enough memory."); X argvrc[line] = rcline[line]; X strcpy(rcline[line], ptr); X while (*ptr) X ptr++; X } X } X } X fclose(rcfp); X } X header.nbuf[0] = 0; X if (line != -1) { X#ifdef DEBUG X for (i = 0; i <= line; i++) X fprintf(stderr, "options: %s\n", rcline[i]); X#endif X process(line+2, argvrc); X do { X#ifdef DEBUG X fprintf(stderr, "Freeing %d\n", line); X#endif X free(rcline[line]); X } while (line--); X } X X if (!*header.nbuf) { X strcpy(header.nbuf, DFLTSUB); X ngcat(header.nbuf); X } X strcat(header.nbuf, ADMSUB); X ngcat(header.nbuf); X if (*header.nbuf) X lcase(header.nbuf); X makehimask(header.nbuf, "junk"); X makehimask(header.nbuf, "control"); X makehimask(header.nbuf, "test"); X if (access(newsrc, 0)) { X if (verbose > 1) X printf("No newsrc\n"); X yep(argv); X } X if ((rcfp = fopen(newsrc, "r")) == NULL) X xerror("Cannot open .newsrc file"); X while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) { X if (!nstrip(rcbuf)) X xerror(".newsrc line too long"); X if (++line >= LINES) X xerror("Too many .newsrc lines"); X if ((rcline[line] = malloc(strlen(rcbuf)+1)) == NULL) X xerror("Not enough memory"); X strcpy(rcline[line], rcbuf); X } X if ((actfp = fopen(ACTIVE, "r")) == NULL) X xerror("Cannot open active newsgroups file"); X X#ifdef DEBUG X fprintf(stderr, "header.nbuf = %s\n", header.nbuf); X#endif X nchk(argv); X exit(0); X} X Xnchk(argv) Xchar **argv; X{ X register int i; X register char *ptr; X long l; X long narts; X char saveptr; X int isnews = 0; X char aline[BUFLEN]; X X#ifdef DEBUG X fprintf(stderr, "nchk()\n"); X#endif X while (fgets(aline, sizeof aline, actfp) != NULL) { X sscanf(aline, "%s %ld", bfr, &narts); X#ifdef DEBUG X fprintf(stderr, "bfr = '%s'\n", bfr); X#endif X if (narts == 0) X continue; X ngcat(bfr); X if (!ngmatch(bfr, nflag ? narggrp : header.nbuf)) X continue; X ngdel(bfr); X i = findrcline(bfr); X if (i < 0) { X if (verbose>1) X printf("No newsrc line for newsgroup %s\n", bfr); X strcpy(rcbuf, " 0"); X } else X strcpy(rcbuf, rcline[i]); X ptr = rcbuf; X X if (index(rcbuf, '!') != NULL) X continue; X if (index(rcbuf, ',') != NULL) { X if (verbose > 1) X printf("Comma in %s newsrc line\n", bfr); X else { X isnews++; X continue; X } X } X while (*ptr) X ptr++; X while (!isdigit(*--ptr) && *ptr != ':' && ptr >= rcbuf) X ; X if (*ptr == ':') X continue; X if (ptr < rcbuf) { X if (verbose > 1) X printf("Ran off beginning of %s newsrc line.\n", bfr); X yep(argv); X } X while (isdigit(*--ptr)) X ; X sscanf(++ptr, "%ld", &l); X if (narts > l) { X if (verbose) { X printf("News: %s ...\n", bfr); X if (verbose < 2) X y = 0; X } X yep(argv); X } Xcontin:; X } X if (isnews) X yep(argv); X if (n) X printf("No news is good news.\n"); X} X Xyep(argv) Xchar **argv; X{ X if (y) { X if (verbose) X printf("There is probably news"); X else X printf("There is news"); X if (nflag) { X narggrp[strlen(narggrp)-1] = '.'; X printf(" in %s\n",narggrp); X } X else X printf(".\n"); X } X if (e) { X#ifdef V6 X execv("/usr/bin/readnews", argv); X#else X execvp("readnews", argv); X#endif X perror("Cannot exec readnews."); X } X if (q) X exit(1); X else X exit(0); X} X Xxerror(message, arg1, arg2) Xchar *message; Xint arg1, arg2; X{ X char buffer[128]; X X sprintf(buffer, message, arg1, arg2); X fprintf(stderr, "checknews: %s.\n", buffer); X exit(1); X} X X/* X * Append NGDELIM to string. X */ Xngcat(s) Xregister char *s; X{ X if (*s) { X while (*s++); X s -= 2; X if (*s++ == NGDELIM) X return; X } X *s++ = NGDELIM; X *s = '\0'; X} X X/* X * News group matching. X * X * nglist is a list of newsgroups. X * sublist is a list of subscriptions. X * sublist may have "meta newsgroups" in it. X * All fields are NGDELIM separated, X * and there is an NGDELIM at the end of each argument. X * X * Currently implemented glitches: X * sublist uses 'all' like shell uses '*', and '.' like shell '/'. X * If subscription X matches Y, it also matches Y.anything. X */ Xngmatch(nglist, sublist) Xregister char *nglist, *sublist; X{ X register char *n, *s; X register int rc; X X rc = FALSE; X for (n = nglist; *n != '\0' && rc == FALSE;) { X for (s = sublist; *s != '\0';) { X if (*s != NEGCHAR) X rc |= ptrncmp(s, n); X else X rc &= ~ptrncmp(s+1, n); X while (*s++ != NGDELIM); X } X while (*n++ != NGDELIM); X } X return(rc); X} X X/* X * Compare two newsgroups for equality. X * The first one may be a "meta" newsgroup. X */ Xptrncmp(ng1, ng2) Xregister char *ng1, *ng2; X{ X while (*ng1 != NGDELIM) { X if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') { X ng1 += 3; X while (*ng2 != NGDELIM && *ng2 != '.') X if (ptrncmp(ng1, ng2++)) X return(TRUE); X return (ptrncmp(ng1, ng2)); X } else if (*ng1++ != *ng2++) X return(FALSE); X } X return (*ng2 == '.' || *ng2 == NGDELIM); X} X X/* X * Get user name and home directory. X */ Xgetuser() X{ X static int flag = TRUE; X register struct passwd *p; X X if (flag) { X if ((p = getpwuid(getuid())) == NULL) X xerror("Cannot get user's name"); X if (username == NULL || *username == '\0') X username = AllocCpy(p->pw_name); X userhome = AllocCpy(p->pw_dir); X flag = FALSE; X } X} X X/* X * Strip trailing newlines, blanks, and tabs from 's'. X * Return TRUE if newline was found, else FALSE. X */ Xnstrip(s) Xregister char *s; X{ X register char *p; X register int rc; X X rc = FALSE; X p = s; X while (*p) X if (*p++ == '\n') X rc = TRUE; X while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t')); X *++p = '\0'; X return(rc); X} X X/* X * Delete trailing NGDELIM. X */ Xngdel(s) Xregister char *s; X{ X if (*s++) { X while (*s++); X s -= 2; X if (*s == NGDELIM) X *s = '\0'; X } X} X Xlcase(s) Xregister char *s; X{ X register char *ptr; X X for (ptr = s; *ptr; ptr++) X if (isupper(*ptr)) X *ptr = tolower(*ptr); X} X X/* X * finds the line in your .newsrc file (actually the in-core "rcline" X * copy of it) and returns the index into the array where it was found. X * -1 means it didn't find it. X * X * We play clever games here to make this faster. It's inherently X * quadratic - we spend lots of CPU time here because we search through X * the whole .newsrc for each line. The "prev" variable remembers where X * the last match was found; we start the search there and loop around X * to the beginning, in the hopes that the calls will be roughly in order. X */ Xint Xfindrcline(name) Xchar *name; X{ X register char *p, *ptr; X register int cur; X register int i; X register int top; X static int prev = 0; X X top = line; i = prev; Xloop: X for (; i <= top; i++) { X for (p = name, ptr = rcline[i]; (cur = *p++); ) { X if (cur != *ptr++) X goto contin2; X } X if (*ptr != ':' && *ptr != '!') X continue; X prev = i; X return i; Xcontin2: X ; X } X if (i > line && line > prev-1) { X i = 0; X top = prev-1; X goto loop; X } X return -1; X} X X/* X * Forbid newsgroup ng, unless he asked for it in nbuf. X */ Xmakehimask(nbuf, ng) Xchar *nbuf, *ng; X{ X if (!findex(nbuf, ng)) { X ngcat(nbuf); X strcat(nbuf, "!"); X strcat(nbuf, ng); X ngcat(nbuf); X } X} X X/* X * Return true if the string searchfor is in string, but not if preceded by !. X */ Xfindex(string, searchfor) Xchar *string, *searchfor; X{ X register char first; X register char *p; X X first = *searchfor; X for (p=index(string, first); p; p = index(p+1, first)) { X if (p>string && p[-1] != '!' && strncmp(p, searchfor, strlen(searchfor)) == 0) X return TRUE; X } X return FALSE; X} X Xxxit(i) X{ X exit(i); X} END_OF_FILE if test 11026 -ne `wc -c <'checknews.c'`; then echo shar: \"'checknews.c'\" unpacked with wrong size! fi # end of 'checknews.c' fi if test -f 'install.sh' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'install.sh'\" else echo shar: Extracting \"'install.sh'\" \(9680 characters\) sed "s/^X//" >'install.sh' <<'END_OF_FILE' X: '@(#)install.sh 1.17 12/16/86' X Xif test "$#" != 6 Xthen X echo "usage: $0 spooldir libdir bindir nuser ngroup ostype" X exit 1 Xfi XSPOOLDIR=$1 XLIBDIR=$2 XBINDIR=$3 XNEWSUSR=$4 XNEWSGRP=$5 XOSTYPE=$6 X X: Get name of local system Xcase $OSTYPE in X usg) SYSNAME=`uname -n` X if test ! -d $LIBDIR/history.d X then X mkdir $LIBDIR/history.d X chown $NEWSUSR $LIBDIR/history.d X chgrp $NEWSGRP $LIBDIR/history.d X fi;; X v7) SYSNAME=`uuname -l` X touch $LIBDIR/history.pag $LIBDIR/history.dir;; X *) echo "$0: Unknown Ostype" X exit 1;; Xesac X Xif test "$SYSNAME" = "" Xthen X echo "$0: Cannot get system name" X exit 1 Xfi X X: Ensure SPOOLDIR exists Xfor i in $SPOOLDIR $SPOOLDIR/.rnews Xdo X if test ! -d $i X then X mkdir $i X fi X chmod 777 $i X chown $NEWSUSR $i X chgrp $NEWSGRP $i Xdone X Xchown $NEWSUSR $LIBDIR Xchgrp $NEWSGRP $LIBDIR X X: Ensure certain files in LIBDIR exist Xtouch $LIBDIR/history $LIBDIR/active $LIBDIR/log $LIBDIR/errlog $LIBDIR/users Xchmod 666 $LIBDIR/users X X: If no sys file, make one. Xif test ! -f $LIBDIR/sys Xthen Xecho Xecho Making a $LIBDIR/sys file to link you to oopsvax. Xecho You must change oopsvax to your news feed. Xecho If you are not in the USA, remove '"usa"' from your line in the sys file. Xecho If you are not in North America, remove '"na"' from your line in the sys file. X cat > $LIBDIR/sys << EOF X$SYSNAME:world,comp,sci,news,rec,soc,talk,misc,net,mod,na,usa,to:: Xoopsvax:world,comp,sci,news,rec,soc,talk,misc,net,mod,na,usa,to.oopsvax:: XEOF Xfi X X: If no seq file, make one. Xif test ! -s $LIBDIR/seq Xthen X echo '100' >$LIBDIR/seq Xfi X X: If no mailpaths, make one. Xif test ! -s $LIBDIR/mailpaths Xthen X cat <$LIBDIR/mailpaths Xbackbone %s Xinternet %s XE_O_F Xecho "I have created $LIBDIR/mailpaths for you. The paths are certainly wrong." Xecho "You must correct them manually to be able to post to moderated groups." Xfi X Xsh makeactive.sh $LIBDIR $SPOOLDIR $NEWSUSR $NEWSGRP X Xfor i in $LIBDIR/ngfile $BINDIR/inews $LIBDIR/localgroups $LIBDIR/moderators \ X $LIBDIR/cunbatch $LIBDIR/c7unbatch Xdo X if test -f $i X then X echo "$i is no longer used. You should remove it." X fi Xdone X Xfor i in $LIBDIR/csendbatch $LIBDIR/c7sendbatch Xdo X if test -f $i X then X echo "$i is no longer used. You should remove it after" X echo "changing your crontab entry to use sendbatch [flags]" X fi Xdone X Xif test -f $BINDIR/cunbatch Xthen X echo "$BINDIR/cunbatch is not used by the new batching scheme." X echo "You should remove it when all of your neighbors have upgraded." Xfi X Xcat >$LIBDIR/aliases.new </tmp/$$aliases X sort $LIBDIR/aliases.new | sed -e 's/ */ /g' -e 's/ */ /g' >/tmp/$$aliases.new X comm -23 /tmp/$$aliases.new /tmp/$$aliases >/tmp/$$comm X if test -s /tmp/$$comm X then X echo "The following suggested aliases are missing or incorrect in your" X echo "$LIBDIR/aliases file. It is suggested you add them." X echo "" X cat /tmp/$$comm X echo "" X echo "A suggested aliases file has been left in $LIBDIR/aliases.new" X echo "for your convenience." X rm /tmp/$$comm /tmp/$$aliases X else X rm /tmp/$$comm /tmp/$$aliases $LIBDIR/aliases.new X fi Xfi X X: if no distributions file, make one Xif test ! -f $LIBDIR/distributions Xthen X cat >$LIBDIR/distributions <'recnews.c' <<'END_OF_FILE' X/* X * recnews [to newsgroup] [from user] X * X * Process a news article which has been mailed to some group like msgs. X * Such articles are in normal mail format and have never seen the insides X * of netnews. If the "to newsgroup" is included, the article is posted X * to this newsgroup instead of trying to intuit it from the headers. X * If the "from user" is included, the return address is forged to look X * like that user instead of what getuid or a from line says. X * X * It is recommended that you always include the to newsgroup, since the X * intuition code is flakey and out of date. The from user is probably X * appropriate for arpanet mailing lists being funnelled at ucbvax but X * not otherwise. Sample lines in /usr/lib/aliases (if you run delivermail): X * worldnews: "|/usr/lib/news/recnews net.general" X * Allows you to mail to worldnews rather than using inews. X * Intended for humans to mail to. X * post-unix-wizards: "|/usr/lib/news/recnews fa.unix-wizards unix-wizards" X * Causes mail to post-unix-wizards to be fed into fa.unix-wizards X * and the return address forged as unix-wizards on the local X * machine. post-unix-wizards (on the local machine) should X * be part of the master mailing list somewhere (on a different X * machine.) X * X * Recnews is primarily useful in remote places on the usenet which collect X * mail from mailing lists and funnel them into the network. It is also X * useful if you like to send mail to some user instead of invoking X * inews -t .. -n .. when you want to submit an article. (Many mailers give X * you nice facilities like editing the message.) It is not, however, X * essential to use recnews to be able to join usenet. X * X * WARNING: recnews disables the "recording" check - it has to because X * by the time inews is run, it's in the background and too late to X * ask permission. If you depend heavily on recordings you probably X * should not allow recnews (and thus the mail interface) to be used. X* X * 1) We leave the from line alone. Just escape the double quotes, but let the X * mailer do the rest. X * 2) We give precedence to "From:" over "From " or ">From " in determining X * who the article is really from. X * Modifications by rad@tek X */ X X#ifdef SCCSID Xstatic char *SccsId = "@(#)recnews.c 2.13 10/23/86"; X#endif /* SCCSID */ X X#include "defs.h" X X#include X#include X X/* X * Note: we assume there are 2 kinds of hosts using recnews: X * Those that have delivermail (and hence this program will never X * have to deal with more than one message at a time) and those on the arpanet X * that do not (and hence all messages end with a sentinel). It is X * supposed that regular v7 type systems without delivermail or some X * other automatic forwarding device will just use rnews. We do X * not attempt to tell where a message ends on all systems due to the X * different conventions in effect. (This COULD be fixed, I suppose.) X */ X X/* X * Kinds of lines in a message. X */ X#define FROM 001 /* From line */ X#define SUBJ 002 /* Subject */ X#define TO 003 /* To (newgroup based on this) */ X#define BLANK 004 /* blank line */ X#define EOM 005 /* End of message (4 ctrl A's) */ X#define HEADER 006 /* any unrecognized header */ X#define TEXT 007 /* anything unrecognized */ X#define INCLUSIVE 010 /* newsgroup is already in header */ X X/* X * Possible states program can be in. X */ X#define SKIPPING 0100 /* In header of message */ X#define READING 0200 /* In body of message */ X X#define BFSZ 250 X X#define EOT '\004' X Xchar from[BFSZ]; /* mailing address for replies */ Xchar sender[BFSZ]; /* mailing address of author, if different */ Xchar to[BFSZ]; /* Destination of mail (msgs, etc) */ Xchar subject[BFSZ]; /* subject of message */ Xchar newsgroup[BFSZ]; /* newsgroups of message */ Xint fromset; /* from passed on command line */ Xchar cmdbuf[BFSZ]; /* command to popen */ X Xextern char *strcat(), *strcpy(); Xextern FILE *popen(); Xchar *any(); X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X char buf[BFSZ], inews[BFSZ]; X register char *p, *q; X register FILE *pipe = NULL; X register int state; X X /* build inews command */ X#ifdef IHCC X sprintf(inews, "%s/%s/%s", logdir(HOME), LIBDIR, "inews"); X#else X sprintf(inews, "%s/%s", LIBDIR, "inews"); X#endif X X if (argc > 1) X strcpy(to, argv[1]); X if (argc > 2) X strcpy(from, argv[2]); X X /* X * Flag that we know who message is from to avoid trying to X * decipher the From line. X */ X if (argc > 2 && (argv[2][0] != '\0')) X fromset++; X X#ifdef debug X printf("argv[0] is <%s>, argv[1] is <%s>, argv[2] is <%s>\n", X argv[0], argv[1], argv[2]); X#endif X state = SKIPPING; X while (fgets(buf, BFSZ, stdin) != NULL) { X if (state == READING) { X fputs(buf,pipe); X continue; X } X switch (type(buf)) { X X case FROM: X frombreak(buf, from); X break; X X case SUBJ: X p = any(buf, " \t"); X if (p == NULL) X p = buf + 8; X q = subject; X while (*++p) { X if (*p == '"') X *q++ = '\\'; X *q++ = *p; X } X q[-1] = '\0'; X break; X X case TO: X if (to[0]) X break; /* already have one */ X p = any(buf, " \t"); X if (p == NULL) X p = buf + 3; X q = to; X while (*++p) { X if (*p == '"') X *q++ = '\\'; X *q++ = *p; X } X q[-1] = '\0'; X break; X X case INCLUSIVE: X sprintf(cmdbuf,"exec %s -p", inews); X pipe = popen(cmdbuf,"w"); X if (pipe == NULL){ X perror("recnews: open failed"); X exit(1); X } X state = READING; X fputs(buf,pipe); X break; X X /* X * Kludge to compensate for messages without real headers X */ X case HEADER: X break; X X case BLANK: X state = READING; X strcpy(newsgroup, to); X sprintf(cmdbuf, "exec %s -t \"%s\" -n \"%s\" -f \"%s\"", X inews, *subject ? subject : "(none)", X newsgroup, from); X#ifdef debug X pipe = stdout; X printf("BLANK: %s\n", cmdbuf); X#else X pipe = popen(cmdbuf, "w"); X if (pipe == NULL) { X perror("recnews: popen failed"); X exit(1); X } X#endif X if (sender[0]) { X fputs(sender, pipe); X putc('\n', pipe); X } X break; X X case TEXT: X strcpy(newsgroup, to); X state = READING; X if (subject[0] == 0) { X strcpy(subject, buf); X if (subject[strlen(subject)-1] == '\n') X subject[strlen(subject)-1] = '\0'; X } X sprintf(cmdbuf, "exec \"%s\" -t \"%s\" -n \"%s\" -f \"%s\"", X inews, subject, newsgroup, from); X#ifdef debug X pipe = stdout; X printf("TEXT: %s\n", cmdbuf); X#else X pipe = popen(cmdbuf, "w"); X if (pipe == NULL) { X perror("pipe failed"); X exit(1); X } X#endif X if (sender[0]){ X fputs(sender, pipe); X putc('\n',pipe); X } X break; X } X } X exit(0); X} X Xtype(p) Xregister char *p; X{ X char *firstbl; X static char lasthdr = 1; /* prev line was a header */ X X if ((*p == ' ' || *p == '\t') && lasthdr) X return HEADER; /* continuation line */ X firstbl = any(p, " \t"); X while (*p == ' ' || *p == '?' || *p == '\t') X ++p; X X if (*p == '\n' || *p == 0) X return BLANK; X if (strncmp(p, ">From", 5) == 0 || strncmp(p, "From", 4) == 0) X return FROM; X if (strncmp(p, "Subj", 4)==0 || strncmp(p, "Re:", 3)==0 || X strncmp(p, "re:", 3)==0) X return SUBJ; X if (strncmp(p, "To", 2)==0) X return TO; X if (strncmp(p, "\1\1\1\1", 4)==0) X return EOM; X if (firstbl && firstbl[-1] == ':' && isalpha(*p)) X return HEADER; X lasthdr = 0; X return TEXT; X} X X/* X * Figure out who a message is from. X */ Xfrombreak(buf, fbuf) Xregister char *buf, *fbuf; X{ X register char *p, *q; X X if (fbuf[0] && fromset) { /* we already know who it's from */ X if (sender[0] == 0 || buf[4] == ':') { X#ifdef debug X printf("sender set to: %s", buf); X#endif X strcpy(sender, buf); X } X return; X } X /* X * Leave fancy Froms alone - this parsing is done by mail X * Just quote the double quotes to prevent interpetation X * by the shell. X * rad@tek X */ X p = any(buf, " \t"); X if (p==NULL) X p = buf + 4; X q = fbuf; X while (*++p) { X if (*p == '"') X *q++ = '\\'; X *q++ = *p; X } X q[-1] = '\0'; X if ((p=(char *)index(fbuf,'\n')) != NULL) X *p = '\0'; X if (buf[4] == ':') X fromset++; X} X X/* X * Return the ptr in sp at which a character in sq appears; X * NULL if not found X * X */ Xchar * Xany(sp, sq) Xchar *sp, *sq; X{ X register c1, c2; X register char *q; X X while (c1 = *sp++) { X q = sq; X while (c2 = *q++) X if (c1 == c2) X return(--sp); X } X return(NULL); X} END_OF_FILE if test 8212 -ne `wc -c <'recnews.c'`; then echo shar: \"'recnews.c'\" unpacked with wrong size! fi # end of 'recnews.c' fi echo shar: End of shell archive. exit 0 -- "Zeta Microcomputer Software" ACSnet: nick@ultima.cs.uts.oz UUCP: ...!uunet!munnari!ultima.cs.uts.oz!nick Fidonet: Nick Andrew on 3:713/602 (Zeta)