rsalz@uunet.UU.NET (Rich Salz) (10/23/87)
Submitted-by: utzoo!henry (Henry Spencer)
Posting-number: Volume 12, Issue 39
Archive-name: cnews/part14
#! /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 <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 14 (of 14)."
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'rna/readnews.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rna/readnews.c'\"
else
echo shar: Extracting \"'rna/readnews.c'\" \(26200 characters\)
sed "s/^X//" >'rna/readnews.c' <<'END_OF_FILE'
X/*
X * readnews
X *
X * Michael Rourke (UNSW) April 1984
X */
X
X#include "defs.h"
X
X#define ARTSEP "/"
X
Xchar postnews[] = POSTNEWS;
Xchar admsub[] = ADMSUB;
Xchar dfltsub[] = DFLTSUB;
Xchar *mailpath = MAIL;
X
X#define MAXARGV 10 /* used in building argv[]s below */
X
X#ifndef NETID
Xchar systemid[DIRSIZ];
X#else
Xchar systemid[] = NETID;
X#endif
X
Xbool iflag; /* -i ignore .newsrc */
Xbool lflag; /* -l print headers only */
Xbool cflag; /* -c check for news only */
Xbool pflag; /* -p print everything selected */
Xchar **uflag; /* -u messagid (unsubscribe from followups) */
Xint usize; /* number of uflag entries */
Xbool Cflag; /* -C verbose -c */
Xbool sflag; /* -s print newsgroup subscription list */
Xbool splus; /* -s+ */
Xbool slistall; /* -s? */
Xbool sminus; /* -s- */
Xchar *sarg; /* arg to -s[+-] */
Xchar *nflag; /* -n newsgroups */
Xextern char *rcgrps; /* -n newsgroups from newsrc file */
Xbool n_on_cline; /* nflag set on command line */
X
Xextern newsrc *rc; /* internal .newsrc */
X
Xactive *alist; /* internal active list */
X
X#if MANGRPS
Xchar *mangrps; /* mandatory subsciption list */
X#endif
X
X#if AUSAM
Xstruct pwent pe; /* current user passwd struct */
Xchar sbuf[SSIZ]; /* passwd strings */
X#else
Xstruct passwd *pp; /* current user passwd struct */
X#endif
Xlong now; /* current time */
Xbool interrupt; /* if interrupt hit */
Xchar *newsdir; /* %news */
Xuid_t newsuid; /* %news uid (not used) */
Xbool su; /* if super user (not used) */
X
Xapplycom list(), check(), commands();
Xvoid *onintr();
Xbool ureject(), seen(), subs(), subsub();
X
X#if MANGRPS
Xchar *getmangrps();
X#endif
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X char buf[BUFSIZ], *p;
X
X setbuf(stdout, buf); /* TODO: remove this? */
X if (options(--argc, ++argv, true)) {
X (void) fprintf(stderr, "Usage: readnews [-n newsgroups] [-i] [-clpC] [-s[-+? [group]]] [-u messageid]\n");
X exit(1);
X }
X now = time(&now);
X
X#if AUSAM
X pe.pw_strings[LNAME] = NEWSROOT;
X if (getpwuid(&pe, sbuf, sizeof(sbuf)) == PWERROR)
X error("Password file error.");
X newsdir = newstr(pe.pw_strings[DIRPATH]);
X newsuid = pe.pw_limits.l_uid;
X#else
X if ((pp = getpwnam(NEWSROOT)) == NULL)
X error("Password file error.");
X newsdir = newstr(pp->pw_dir);
X newsuid = pp->pw_uid;
X#endif
X
X#if AUSAM
X#if MANGRPS
X pe.pw_limits.l_uid = getuid();
X if (getpwlog(&pe, NIL(char), 0) == PWERROR) /* want pw_cmask */
X error("Password file error.");
X#endif
X pwclose();
X#else
X pp = NIL(struct passwd );
X endpwent();
X#endif
X
X#ifndef NETID
X getaddr(G_SYSNAME, systemid);
X#endif
X
X if (!iflag)
X readnewsrc();
X
X if (nflag)
X convgrps(nflag);
X else
X nflag = dfltsub;
X if (rcgrps)
X convgrps(rcgrps);
X if (!n_on_cline) {
X#if MANGRPS
X int addsub();
X
X if (mangrps = getmangrps(pe.pw_cmask))
X applyng(mangrps, addsub, &nflag);
X#endif
X if (!ngmatch(admsub, nflag))
X nflag = newstr3(admsub, NGSEPS, nflag);
X }
X if ((int) sflag + (int) lflag + (int) cflag + (int) pflag > 1)
X error("-clpsC flags are mutually exclusive.");
X if (uflag)
X qsort((char *) uflag, (unsigned) usize, sizeof(char *), strpcmp);
X
X /* user has private mailer? */
X if ((p = getenv("MAILER")) != NULL)
X mailpath = newstr(p);
X
X alist = readactive();
X
X if (sflag) {
X if (subs() && !iflag)
X writenewsrc(alist);
X } else if (lflag)
X apply(alist, nflag, list, false);
X else if (cflag)
X apply(alist, nflag, check, false);
X else {
X if (!pflag) {
X if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X (void) signal(SIGINT, onintr);
X if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
X (void) signal(SIGQUIT, onintr);
X }
X apply(alist, nflag, commands, true);
X if (!iflag)
X writenewsrc(alist);
X }
X exit(0);
X}
X
X#if MANGRPS
X/*
X * make a subscription list of all class groups the user belongs too
X * (mandatory subscription)
X */
Xchar *
Xgetmangrps(cmask)
Xchar *cmask;
X{
X static char *weekday[] = {
X "mon", "tue", "wed", "thu", "fri" };
X register char **classes;
X register char *s, *end;
X register char *grp;
X register int i, size;
X extern char **getclasses();
X
X grp = NIL(char);
X if ((classes = getclasses(cmask)) == NIL(char *))
X error("Can't get classes.");
X while (*classes) {
X if (isdigit(**classes)) {
X /*
X * trim string after numeric class
X * if it is a day of the week
X */
X s = *classes;
X while (isdigit(*s) || *s == '.')
X s++;
X if (*s) {
X end = s;
X while (isalpha(*end))
X end++;
X if (*end && end != s && end - s <= 3) {
X size = end - s;
X for (i = 0; i < 5; i++)
X if (CMPN(s, weekday[i], size) == 0)
X break;
X if (i != 5)
X *s = '\0';
X }
X }
X }
X grp = (grp? catstr2(grp, ",class.", *classes):
X newstr2("class.", *classes));
X classes++;
X }
X return grp;
X}
X
X/*
X * if newsgroup "ng" isn't subscribed to, add it to subscription list
X */
Xaddsub(ng, slist)
Xchar *ng;
Xchar **slist;
X{
X if (!ngmatch(ng, *slist))
X *slist = newstr3(ng, NGSEPS, *slist);
X}
X
X#endif
X
Xvoid *
Xonintr()
X{
X if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X (void) signal(SIGINT, onintr);
X if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
X (void) signal(SIGQUIT, onintr);
X interrupt = true;
X}
X
X/*
X * process options
X * can be called from readnewsrc()
X */
Xoptions(argc, argv, cline)
Xint argc;
Xchar *argv[];
Xbool cline;
X{
X register char c;
X
X /* TODO: use getopt(3) */
X while (argc > 0) {
X if (argv[0][0] != '-')
X break;
X while (c = *(++(argv[0]))) {
X switch (c) {
X case 'n':
X if (cline)
X nflag = argv[1], n_on_cline = true;
X else {
X if (!n_on_cline)
X nflag = (nflag?
X catstr2(nflag, NGSEPS, argv[1]):
X newstr(argv[1]));
X rcgrps = (rcgrps?
X catstr2(rcgrps, NGSEPS, argv[1]):
X newstr(argv[1]));
X }
X argc--, argv++;
X break;
X case 'u':
X usize++;
X uflag = (uflag? (char **)myrealloc((char *)uflag,
X (int)sizeof(char *) * usize):
X (char **)myalloc((int)sizeof(char *)));
X uflag[usize - 1] = newstr(argv[1]);
X argc--, argv++;
X break;
X case 'i':
X iflag = true;
X continue;
X case 's':
X sflag = true;
X switch (argv[0][1]) {
X case '\0':
X continue;
X case '+':
X splus = true;
X break;
X case '?':
X slistall = true, ++(argv[0]);
X continue;
X case '-':
X sminus = true;
X break;
X default:
X argc = -1;
X break;
X }
X if (argc > 0) {
X sarg = newstr(argv[1]);
X argc--, argv++;
X }
X break;
X case 'p':
X pflag = true;
X continue;
X case 'l':
X lflag = true;
X continue;
X case 'c':
X cflag = true;
X continue;
X case 'C':
X cflag = Cflag = true;
X continue;
X default:
X argc = -1;
X break;
X }
X break;
X }
X argc--, argv++;
X }
X return argc != 0;
X}
X
X/*
X * subscription list handling
X * return true if newsrc is to be re-written
X */
Xbool
Xsubs()
X{
X register newsrc *np;
X register active *ap;
X register char *tmp, *com;
X register FILE *f;
X
X if (slistall) {
X (void) printf("Active newsgroups:\n");
X (void) fflush(stdout);
X#ifdef MC /* gok. probably a local paginator */
X com = newstr2("exec ", MC);
X if ((f = popen(com, "w")) == NULL)
X f = stdout;
X free(com);
X#else
X f = stdout;
X com = 0; /* for lint */
X com = com; /* for lint */
X#endif
X for (ap = alist; ap; ap = ap->a_next)
X (void) fprintf(f, "%s\n", ap->a_name);
X#ifdef MC
X if (f != stdout)
X pclose(f);
X#endif
X return false;
X } else if (splus || sminus) {
X if (strpbrk(sarg, BADGRPCHARS)) {
X (void) printf("%s: Illegal char in newsgroup.\n", sarg);
X return false;
X }
X if (ngmatch(sarg, nflag)) {
X /*
X * normally we subscribe, check for an exclusion
X */
X for (np = rc; np; np = np->n_next)
X if (CMP(sarg, np->n_name) == 0)
X break;
X if (np) {
X /*
X * altering subscribe flag is all
X * we need to change
X */
X np->n_subscribe = splus;
X return true;
X }
X if (sminus) {
X /*
X * try deleting from sub list
X */
X if (subsub(sarg, rcgrps))
X return true;
X /*
X * add specific exclusion
X */
X rcgrps = newstr4(rcgrps, NGSEPS, NEGS, sarg);
X return true;
X }
X } else if (splus) {
X /*
X * we don't subscribe,
X * try deleting !sarg first
X */
X tmp = newstr2(NEGS, sarg);
X subsub(tmp, rcgrps);
X if (!ngmatch(sarg, rcgrps))
X /*
X * didn't work, so add explicit subscription
X */
X rcgrps = rcgrps? newstr3(rcgrps, NGSEPS, sarg):
X newstr(sarg);
X return true;
X }
X } else {
X (void) printf("Subscription list: %s", nflag);
X for (np = rc; np; np = np->n_next)
X if (!np->n_subscribe && ngmatch(np->n_name, nflag))
X (void) printf(",!%s", np->n_name);
X (void) printf("\n");
X }
X return false;
X}
X
X
X/*
X * try and delete group from subscription list
X * return true if successful
X */
Xbool
Xsubsub(grp, slist)
Xchar *grp;
Xchar *slist;
X{
X register char *delim;
X
X while (*slist) {
X if (delim = strchr(slist, NGSEPCHAR))
X *delim = '\0';
X if (CMP(grp, slist) == 0) {
X if (delim)
X (void) strcpy(slist, delim + 1);
X else if (slist[-1] = ',')
X slist[-1] = '\0';
X else
X slist[0] = '\0';
X return true;
X }
X if (delim)
X *delim = NGSEPCHAR, slist = delim + 1;
X else
X break;
X }
X return false;
X}
X
X/*
X * list titles command (-l)
X */
Xapplycom
Xlist(ap, np)
Xactive *ap;
Xnewsrc *np;
X{
X static active *lastap;
X static bool first = true;
X register char *fname;
X register FILE *f;
X header h;
X ino_t ino;
X
X np->n_last++;
X fname = convg(newstr5(newsdir, "/", ap->a_name, ARTSEP,
X itoa(np->n_last)));
X ino = 0;
X f = fopen(fname, "r");
X free(fname);
X if (!f || seen(f, &ino))
X return next;
X gethead(f, &h);
X if (uflag && h.h_references && ureject(&h)) {
X freehead(&h);
X return next;
X }
X if (first) {
X (void) printf("News articles:\n");
X first = false;
X }
X if (lastap != ap)
X (void) printf(" %s:\n", ap->a_name);
X lastap = ap;
X (void) printf(" %-4d %s\n", np->n_last, h.h_subject);
X (void) fclose(f);
X freehead(&h);
X if (ino)
X seen(NIL(FILE), &ino);
X return next;
X}
X
X/*
X * check command (-c or -C)
X */
Xapplycom
Xcheck(ap, np)
Xactive *ap;
Xnewsrc *np;
X{
X static bool done;
X register int num;
X
X np->n_last++;
X if (Cflag) {
X if (!done)
X (void) printf("You have news:\n");
X done = true;
X num = ap->a_seq - np->n_last + 1;
X (void) printf("\t%s %d article%s\n", ap->a_name, num, num > 1 ? "s" :
X "");
X return nextgroup;
X } else
X {
X (void) printf("You have news.\n");
X exit(0);
X /* NOTREACHED */
X }
X}
X
X
X/*
X * normal command handler (or pflag)
X * commands:
X *
X * \n print current article
X * + go to next article
X * q quit
X * c cancel
X * r reply
X * m [person] mail
X * f followup
X * p postnews
X * n [newsgrp] next newsgroup
X * s [file] save
X * u unsubscribe from followup
X * U unsubscribe from group
X * !stuff shell escape
X * number or . go to number
X * - back to previous article (toggle)
X * x quick exit
X * h long header info
X * H full header
X *
X * inside r, f or p:
X * .e edit
X * .i interpolate
X * . or EOT terminate message
X * .!comd shell escape
X */
Xapplycom
Xcommands(ap, np, last, pushed)
Xactive *ap;
Xnewsrc *np;
Xbool last;
Xbool pushed;
X{
X static char errmess[] = "Incorrect command; Type `?' for help.\n";
X static char form[] = "%s: %s\n";
X
X static char savedsys[BUFSIZ / 2];
X static active *lastap, *rlastap;
X static newsrc lastn;
X static char number[20];
X static active *wantap;
X
X register char *com, *arg;
X register int c, i, size;
X register FILE *f;
X char *fname;
X header h;
X newsrc ntmp;
X ino_t ino;
X bool printed, pheader, verbose, hadinterrupt;
X applycom nextact;
X
X extern char t_from[], t_subject[], t_date[];
X extern char t_newsgroups[], t_path[], t_sender[];
X extern char t_replyto[], t_organization[];
X extern char *strncpy();
X extern active *activep();
X
X
X if (last) {
X /*
X * give user one last chance to
X * see this article
X */
X ap = rlastap;
X np = &lastn;
X wantap = NIL(active);
X if (!ap || pflag)
X return stop;
X } else if (wantap)
X /*
X * doing an "n newsgroup" command
X */
X if (wantap != ap)
X return nextgroup;
X else
X wantap = NIL(active);
X
X fname = convg(newstr5(newsdir, "/", ap->a_name, ARTSEP,
X itoa(np->n_last + 1)));
X f = fopen(fname, "r");
X ino = 0;
X if (!f || !last && !pushed && seen(f, &ino)) {
X if (pushed)
X (void) printf("Article %d (%s) no longer exists.\n",
X np->n_last + 1, ap->a_name);
X else
X np->n_last++;
X if (f)
X (void) fclose(f);
X free(fname);
X return next;
X }
X
X gethead(f, &h);
X if (!pushed && uflag && h.h_references && ureject(&h)) {
X /* unsubscribed followup */
X freehead(&h);
X np->n_last++;
X (void) fclose(f);
X free(fname);
X return next;
X }
X
X (void) printf("\n");
X interrupt = hadinterrupt = verbose = false;
X if (last) {
X (void) printf("No more articles.\n");
X printed = pheader = true;
X } else
X printed = pheader = false;
X
X while (1) {
X if (lastap != ap) {
X size = strlen(ap->a_name) + sizeof("Newsgroup");
X for (i = 0; i < size; i++)
X (void) putc('-', stdout);
X (void) printf("\nNewsgroup %s\n", ap->a_name);
X for (i = 0; i < size; i++)
X (void) putc('-', stdout);
X (void) printf("\n\n");
X }
X lastap = ap;
X if (!pheader) {
X (void) printf("Article %d of %d (%s)",
X np->n_last + 1, ap->a_seq, ap->a_name);
X if (h.h_lines != 0)
X (void) printf(" (%s lines)", h.h_lines);
X (void) printf("\n");
X (void) printf(form, t_subject, h.h_subject);
X (void) printf(form, t_from, h.h_from);
X if (verbose || pflag) {
X (void) printf(form, t_date, h.h_date);
X (void) printf(form, t_newsgroups, h.h_newsgroups);
X (void) printf(form, t_path, h.h_path);
X if (h.h_sender)
X (void) printf(form, t_sender, h.h_sender);
X if (h.h_replyto)
X (void) printf(form, t_replyto, h.h_replyto);
X if (h.h_organisation)
X (void) printf(form, t_organization, h.h_organisation);
X verbose = false;
X }
X pheader = true;
X }
X if (!pushed && number[0])
X /*
X * just returned from a number command
X * and have another to do
X */
X com = number;
X else if (pflag)
X /*
X * just print it
X */
X com = "";
X else
X {
X (void) printf("? ");
X if (fflush(stdout) == EOF) {
X (void) printf("\n? ");
X (void) fflush(stdout);
X }
X interrupt = false;
X if ((com = mgets()) == NIL(char)) {
X if (interrupt)
X if (!hadinterrupt) {
X clearerr(stdin);
X (void) printf("Interrupt\n");
X hadinterrupt = true;
X interrupt = false;
X continue;
X }
X else
X exit(1);
X nextact = stop;
X break;
X }
X hadinterrupt = false;
X }
X if (*com == '!') {
X if (com[1] == '!') {
X (void) printf("!%s\n", savedsys);
X com = savedsys;
X } else
X com++;
X (void) fflush(stdout);
X#ifdef F_SETFD
X fcntl(fileno(f), F_SETFD, 1); /* close on exec */
X#endif
X system(com);
X if (com != savedsys)
X strncpy(savedsys, com, sizeof(savedsys) - 1);
X (void) printf("!\n");
X if (!printed)
X pheader = false;
X continue;
X }
X /*
X * check command syntax
X */
X if (*com && !isdigit(*com) && com[1] && (!isspace(com[1]) ||
X strchr("nsm", *com) == NIL(char))) {
X (void) printf(errmess);
X continue;
X }
X if (c = *com) {
X arg = com;
X while (isspace(*++arg))
X ;
X } else
X arg = NIL(char);
X switch (c) {
X case 0:
X case '.':
X if (!printed || c == '.') {
X if (pflag)
X (void) printf("\n");
X print(&h, f);
X if (pflag) {
X nextact = next;
X break;
X }
X printed = true;
X continue;
X }
X case 'n': /* B compatible */
X case '+':
X case ';':
X nextact = next;
X break;
X case '?':
X help();
X continue;
X case 'c':
X cancelarticle(&h);
X continue;
X case 'r':
X reply(&h, fname);
X continue;
X case 'm':
X if (!arg || !*arg)
X (void) printf("Person argument missing.\n");
X else
X mail(&h, fname, arg);
X continue;
X case 'f':
X followup(&h, fname);
X continue;
X case 'p':
X pnews(fname);
X continue;
X case 'U':
X if (ngmatch(np->n_name, ADMSUB)
X#if MANGRPS
X || ngmatch(np->n_name, mangrps))
X#else
X )
X#endif
X {
X (void) printf("Group \"%s\" can't be unsubscribed.\n",
X np->n_name);
X continue;
X }
X np->n_subscribe = false;
X nextact = nextgroup;
X break;
X case 'u':
X unsubscribe(h.h_references);
X nextact = next;
X break;
X case 'N': /* B compatible */
X if (!*arg) {
X nextact = nextgroup;
X break;
X }
X if ((wantap = activep(arg)) == NIL(active)) {
X (void) printf("%s: non-existent newsgroup.\n", arg);
X continue;
X }
X if (!ngmatch(arg, nflag)) {
X (void) printf("%s: is not subscribed to!\n", arg);
X wantap = NIL(active);
X continue;
X }
X nextact = searchgroup;
X break;
X case 's':
X save(&h, f, arg);
X continue;
X case 'q':
X nextact = stop;
X break;
X case 'x':
X exit(0);
X case 'h':
X verbose = true;
X pheader = false;
X continue;
X case 'H':
X puthead(&h, stdout, printing);
X continue;
X case '-':
X if (pushed) {
X nextact = next;
X break;
X }
X if (!rlastap || !lastn.n_name) {
X (void) printf("Can't go back!\n");
X continue;
X }
X nextact = commands(rlastap, &lastn, false, true);
X /*
X * number commands, after a "-" act on the
X * group of the "-" command
X */
X while (number[0]) {
X ntmp = lastn;
X ntmp.n_last = atoi(number) - 1;
X number[0] = '\0';
X nextact = commands(rlastap, &ntmp, false, true);
X }
X if (nextact != next)
X break;
X (void) printf("\n");
X pheader = false;
X continue;
X default:
X if (isdigit(c)) {
X i = c - '0';
X while (isdigit(*arg))
X i = i * 10 + *arg++ - '0';
X }
X if (!isdigit(c) || *arg != '\0') {
X (void) printf(errmess);
X continue;
X }
X number[0] = '\0';
X if (i < ap->a_low || i > ap->a_seq) {
X (void) printf("Articles in \"%s\" group range %d to %d.\n",
X np->n_name, ap->a_low, ap->a_seq);
X continue;
X }
X if (pushed) {
X sprintf(number, "%d", i);
X nextact = next;
X break;
X }
X ntmp = *np;
X ntmp.n_last = i - 1;
X if ((nextact = commands(ap, &ntmp, false, true)) !=
X next)
X break;
X if (!number[0]) {
X (void) printf("\n");
X pheader = false;
X }
X continue;
X }
X break;
X }
X rlastap = ap;
X lastn = *np;
X if (!pushed && (nextact == next || printed)) {
X np->n_last++;
X if (ino)
X seen(NIL(FILE), &ino);
X }
X freehead(&h);
X (void) fclose(f);
X free(fname);
X return nextact;
X}
X
X
X/*
X * see if this is a followup we are ignoring
X */
Xbool
Xureject(hp)
Xregister header *hp;
X{
X register bool found;
X register char *rp, *ids, c;
X char *key[1];
X
X found = false;
X rp = hp->h_references;
X while (*rp && !found) {
X if (ids = strpbrk(rp, " ,")) {
X c = *ids;
X *ids = '\0';
X }
X key[0] = rp;
X found = (bool) (bsearch((char *) key, (char *) uflag, (unsigned) usize,
X sizeof(char *), strpcmp) != NIL(char));
X if (ids)
X *ids = c, rp = ids + 1;
X else
X break;
X while (isspace(*rp) || *rp == ',')
X rp++;
X }
X return found;
X}
X
X
X/*
X * see if the article has links, if so have we seen it?
X * close file if we return true
X *
X * called twice,
X * first (with f set) to test (and possibly set *ino)
X * again to put *ino in memory
X */
Xbool
Xseen(f, ino)
XFILE *f;
Xino_t *ino;
X{
X static int num;
X static ino_t *ilist;
X struct stat statb;
X register int i;
X
X if (f) {
X if (fstat(fileno(f), &statb) != 0 || statb.st_nlink <= 1)
X return false;
X for (i = 0; i < num; i++)
X if (ilist[i] == statb.st_ino) {
X (void) fclose(f);
X return true;
X }
X *ino = statb.st_ino;
X return false;
X } else if (*ino) {
X num++;
X ilist = (ino_t * ) (ilist ? myrealloc((char *) ilist, (int) sizeof(ino_t) *
X num) : myalloc((int) sizeof(ino_t)));
X ilist[num - 1] = *ino;
X }
X return true;
X}
X
X
X/*
X * print out help file
X */
Xhelp()
X{
X register FILE *f;
X register int c;
X static char helppath[] = HELP;
X
X if ((f = fopen(helppath, "r")) == NIL(FILE)) {
X (void) printf("Can't open %s\n", helppath);
X return;
X }
X while ((c = getc(f)) != EOF)
X (void) putc(c, stdout);
X (void) fclose(f);
X}
X
X/*
X * cancel an article.
X * inews does permission checking.
X */
Xcancelarticle(hp)
Xheader *hp;
X{
X char *argv[MAXARGV];
X
X argv[0] = strrchr(postnews, '/') + 1;
X argv[1] = "-c"; /* TODO: no such option in C news */
X argv[2] = newstr2("cancel ", hp->h_messageid);
X argv[3] = "-n";
X argv[4] = hp->h_newsgroups;
X if (hp->h_distribution) {
X argv[5] = "-d";
X argv[6] = hp->h_distribution;
X argv[7] = NIL(char);
X } else
X argv[5] = NIL(char);
X run(postnews, argv, true);
X free(argv[2]);
X}
X
X/*
X * reply to sender by mail
X */
X/* ARGSUSED fname */
Xreply(hp, fname)
Xheader *hp;
Xchar *fname;
X{
X char *argv[MAXARGV];
X register int argc;
X
X argc = 0;
X argv[argc++] = "mail";
X#ifdef UNSWMAIL
X argv[argc++] = "-s";
X if ((argv[argc++] = getsubject(hp)) == NIL(char))
X return;
X argv[argc++] = "-i";
X argv[argc++] = fname;
X#endif
X
X if ((argv[argc++] = getretaddr(hp)) == NIL(char)) {
X (void) printf("Can't work out an address!\n");
X return;
X }
X
X argv[argc++] = NIL(char);
X
X run(mailpath, argv, false);
X
X free(argv[argc - 2]);
X}
X
X
X/*
X * mail to person
X */
X/* ARGSUSED hp fname */
Xmail(hp, fname, person)
Xheader *hp;
Xchar *fname, *person;
X{
X char *argv[MAXARGV];
X register int argc;
X
X argc = 0;
X argv[argc++] = "mail";
X#ifdef UNSWMAIL
X argv[argc++] = "-i";
X argv[argc++] = fname;
X argv[argc++] = "-s";
X argv[argc++] = hp->h_subject;
X#endif
X argv[argc++] = person;
X argv[argc++] = NIL(char);
X
X run(mailpath, argv, false);
X}
X
X
X/*
X * generate correct headers for a followup article
X * then call inews.
X */
Xfollowup(hp, fname)
Xheader *hp;
Xchar *fname;
X{
X register int argc;
X char *argv[10];
X
X argc = 0;
X argv[argc++] = strrchr(postnews, '/') + 1;
X argv[argc++] = "-i"; /* TODO: what's this in B news? */
X argv[argc++] = fname;
X argv[argc++] = "-r";
X if (hp->h_references && hp->h_messageid)
X argv[argc++] = newstr3(hp->h_references, " ", hp->h_messageid);
X else if (hp->h_messageid)
X argv[argc++] = newstr(hp->h_messageid);
X else
X argc--;
X
X argv[argc++] = "-s";
X if ((argv[argc++] = getsubject(hp)) == NIL(char))
X return;
X
X argv[argc++] = "-n";
X if (hp->h_followupto)
X argv[argc++] = hp->h_followupto;
X else
X argv[argc++] = hp->h_newsgroups;
X argv[argc++] = NIL(char);
X
X run(postnews, argv, false);
X
X if (argc == 10)
X free(argv[4]);
X}
X
X/*
X * get correct "Subject: Re: .." line
X */
Xchar *
Xgetsubject(hp)
Xregister header *hp;
X{
X register char *s;
X
X if (!hp->h_subject) {
X (void) printf("Subject: Re: ");
X (void) fflush(stdout);
X if ((s = mgets()) == NIL(char) || !*s) {
X (void) printf("The Subject field is mandatory.\n");
X return NIL(char);
X }
X return newstr2("Re: ", s);
X } else if (CMPN(hp->h_subject, "Re: ", 4) != 0 && CMPN(hp->h_subject,
X "re: ", 4) != 0)
X return newstr2("Re: ", hp->h_subject);
X else
X return hp->h_subject;
X}
X
X
X/*
X * run a command, optionally closing stdin
X */
Xrun(com, argv, closein)
Xchar *com;
Xchar *argv[];
Xbool closein;
X{
X int pid, status, r;
X
X switch (pid = fork()) {
X default:
X /* parent */
X break;
X case 0:
X /* child */
X if (closein)
X close(fileno(stdin));
X execvp(com, argv);
X error("can't exec %s", com);
X exit(1);
X
X case -1:
X error("can't fork");
X }
X
X if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X (void) signal(SIGINT, SIG_IGN);
X if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
X (void) signal(SIGQUIT, SIG_IGN);
X
X while ((r = wait(&status)) != pid && r != -1)
X ;
X
X if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X (void) signal(SIGINT, onintr);
X if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
X (void) signal(SIGQUIT, onintr);
X}
X
X/*
X * call postnews
X */
Xpnews(fname)
Xchar *fname;
X{
X char *argv[MAXARGV];
X
X argv[0] = strrchr(postnews, '/') + 1;
X argv[1] = "-i"; /* TODO: what's this inews option? */
X argv[2] = fname;
X argv[3] = NIL(char);
X run(postnews, argv, false);
X}
X
X/*
X * save an article
X */
Xsave(hp, f, s)
Xheader *hp;
XFILE *f;
Xchar *s;
X{
X register long pos;
X register int c;
X register char *cp;
X register FILE *sf;
X register char *aname;
X long then;
X extern char *getenv();
X
X if (!*s) {
X if ((aname = getenv("HOME")) == NIL(char)) {
X (void) printf("No $HOME in environment.\n");
X return;
X }
X s = aname = newstr3(aname, "/", ARTICLES);
X } else
X aname = NIL(char);
X if ((sf = fopen(s, "a")) == NIL(FILE)) {
X (void) fprintf(stderr, "readnews: can't open %s\n", s);
X return;
X }
X if (aname)
X free(aname);
X pos = ftell(f);
X rewind(f);
X if (cp = strchr(hp->h_from, ' '))
X *cp = '\0';
X if (hp->h_date)
X then = atot(hp->h_date);
X else
X then = 0L;
X (void) fprintf(sf, "From %s %s", hp->h_from, ctime(then ? &then : &now));
X if (cp)
X *cp = ' ';
X while ((c = getc(f)) != EOF)
X (void) putc(c, sf);
X (void) fclose(sf);
X fseek(f, pos, 0);
X}
X
X
X/*
X * unsubscribe from all followup articles
X * on this topic
X */
Xunsubscribe(id)
Xchar *id;
X{
X register char *s, c;
X
X if (!id || !*id) {
X (void) printf("no references! (warning)\n");
X return;
X }
X while (*id) {
X if (s = strpbrk(id, " ,")) {
X c = *s;
X *s = '\0';
X }
X usize++;
X uflag = (uflag ? (char **) myrealloc((char *) uflag, (int) sizeof(char
X *) * usize) : (char **) myalloc((int) sizeof(char *)));
X uflag[usize - 1] = newstr(id);
X if (s)
X *s = c, id = s + 1;
X else
X break;
X while (isspace(*id) || *id == ',')
X id++;
X }
X qsort((char *) uflag, (unsigned) usize, sizeof(char *), strpcmp);
X}
X
X
X/*
X * print an article, if it's long enough call page()
X */
Xprint(hp, f)
Xheader *hp;
XFILE *f;
X{
X register int c;
X register long pos;
X
X pos = ftell(f);
X if (!pflag && hp->h_lines && atoi(hp->h_lines) >= PAGESIZE - 4)
X page(f);
X else
X while ((c = getc(f)) != EOF)
X (void) putc(c, stdout);
X fseek(f, pos, 0);
X}
X
X
X/*
X * copy article text to stdout, and break into pages
X */
Xpage(f)
XFILE *f;
X{
X static char moremess[] = "<CR for more>";
X
X register int c;
X register unsigned lineno;
X char lbuf[80];
X struct sgttyb ttybuf;
X
X gtty(fileno(stdin), &ttybuf);
X if (ttybuf.sg_flags & ECHO) {
X ttybuf.sg_flags &= ~ECHO;
X stty(fileno(stdin), &ttybuf);
X ttybuf.sg_flags |= ECHO;
X }
X lineno = 1;
X while (!interrupt) {
X while (lineno < PAGESIZE - 4 && !interrupt) {
X while ((c = getc(f)) != EOF && c != '\n')
X (void) putc(c, stdout);
X if (c == EOF)
X goto fastexit;
X (void) putc('\n', stdout);
X lineno++;
X }
X if (interrupt)
X break;
X (void) printf(moremess);
X if (fflush(stdout) == EOF)
X break;
X (void) read(fileno(stdin), lbuf, sizeof(lbuf)); /* TODO: fix */
X (void) printf("\r%*s\r", sizeof(moremess), " ");
X lineno = 0;
X }
X if (lineno)
X (void) putc('\n', stdout);
X interrupt = false;
Xfastexit:
X if (ttybuf.sg_flags & ECHO)
X stty(fileno(stdin), &ttybuf);
X}
X
X/* VARARGS1 */
Xerror(s, a0, a1, a2, a3)
Xchar *s;
X{
X (void) fprintf(stderr, "readnews: ");
X (void) fprintf(stderr, s, a0, a1, a2, a3);
X (void) fprintf(stderr, "\n");
X exit(1);
X}
END_OF_FILE
if test 26200 -ne `wc -c <'rna/readnews.c'`; then
echo shar: \"'rna/readnews.c'\" unpacked with wrong size!
fi
# end of 'rna/readnews.c'
fi
echo shar: End of archive 14 \(of 14\).
cp /dev/null ark14isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 14 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
if test -f 'rnews/print' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/print'\"
else
echo shar: Extracting \"'rnews/print'\" \(0 characters\)
sed "s/^X//" >'rnews/print' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/print'`; then
echo shar: \"'rnews/print'\" unpacked with wrong size!
fi
# end of 'rnews/print'
fi
if test -f 'rnews/printc' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/printc'\"
else
echo shar: Extracting \"'rnews/printc'\" \(0 characters\)
sed "s/^X//" >'rnews/printc' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/printc'`; then
echo shar: \"'rnews/printc'\" unpacked with wrong size!
fi
# end of 'rnews/printc'
fi
if test -f 'rnews/printnonc' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/printnonc'\"
else
echo shar: Extracting \"'rnews/printnonc'\" \(0 characters\)
sed "s/^X//" >'rnews/printnonc' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/printnonc'`; then
echo shar: \"'rnews/printnonc'\" unpacked with wrong size!
fi
# end of 'rnews/printnonc'
fi
if test -f 'rnews/test/demo/batch.large' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/test/demo/batch.large'\"
else
echo shar: Extracting \"'rnews/test/demo/batch.large'\" \(0 characters\)
sed "s/^X//" >'rnews/test/demo/batch.large' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/test/demo/batch.large'`; then
echo shar: \"'rnews/test/demo/batch.large'\" unpacked with wrong size!
fi
# end of 'rnews/test/demo/batch.large'
fi
if test -f 'rnews/test/lib/errlog' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/test/lib/errlog'\"
else
echo shar: Extracting \"'rnews/test/lib/errlog'\" \(0 characters\)
sed "s/^X//" >'rnews/test/lib/errlog' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/test/lib/errlog'`; then
echo shar: \"'rnews/test/lib/errlog'\" unpacked with wrong size!
fi
# end of 'rnews/test/lib/errlog'
fi
if test -f 'rnews/test/lib/history' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/test/lib/history'\"
else
echo shar: Extracting \"'rnews/test/lib/history'\" \(0 characters\)
sed "s/^X//" >'rnews/test/lib/history' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/test/lib/history'`; then
echo shar: \"'rnews/test/lib/history'\" unpacked with wrong size!
fi
# end of 'rnews/test/lib/history'
fi
if test -f 'rnews/test/lib/history.dir' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/test/lib/history.dir'\"
else
echo shar: Extracting \"'rnews/test/lib/history.dir'\" \(0 characters\)
sed "s/^X//" >'rnews/test/lib/history.dir' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/test/lib/history.dir'`; then
echo shar: \"'rnews/test/lib/history.dir'\" unpacked with wrong size!
fi
# end of 'rnews/test/lib/history.dir'
fi
if test -f 'rnews/test/lib/history.pag' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/test/lib/history.pag'\"
else
echo shar: Extracting \"'rnews/test/lib/history.pag'\" \(0 characters\)
sed "s/^X//" >'rnews/test/lib/history.pag' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/test/lib/history.pag'`; then
echo shar: \"'rnews/test/lib/history.pag'\" unpacked with wrong size!
fi
# end of 'rnews/test/lib/history.pag'
fi
if test -f 'rnews/test/lib/log' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/test/lib/log'\"
else
echo shar: Extracting \"'rnews/test/lib/log'\" \(0 characters\)
sed "s/^X//" >'rnews/test/lib/log' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/test/lib/log'`; then
echo shar: \"'rnews/test/lib/log'\" unpacked with wrong size!
fi
# end of 'rnews/test/lib/log'
fi
if test -f 'rnews/test/lib/realrnews' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/test/lib/realrnews'\"
else
echo shar: Extracting \"'rnews/test/lib/realrnews'\" \(0 characters\)
sed "s/^X//" >'rnews/test/lib/realrnews' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/test/lib/realrnews'`; then
echo shar: \"'rnews/test/lib/realrnews'\" unpacked with wrong size!
fi
# end of 'rnews/test/lib/realrnews'
fi
if test -f 'rnews/test/time.rnews' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/test/time.rnews'\"
else
echo shar: Extracting \"'rnews/test/time.rnews'\" \(144 characters\)
sed "s/^X//" >'rnews/test/time.rnews' <<'END_OF_FILE'
X#! /bin/sh
XHERE=`pwd`
XPATH=$HERE/lib:/bin:/usr/bin; export PATH
Xtime realrnews -s $HERE/spool -l $HERE/lib <demo/batch.large $* # -d fhlmt # -p
END_OF_FILE
if test 144 -ne `wc -c <'rnews/test/time.rnews'`; then
echo shar: \"'rnews/test/time.rnews'\" unpacked with wrong size!
fi
# end of 'rnews/test/time.rnews'
fi
if test -f 'rnews/vers/bsd42/clsexec.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/vers/bsd42/clsexec.c'\"
else
echo shar: Extracting \"'rnews/vers/bsd42/clsexec.c'\" \(158 characters\)
sed "s/^X//" >'rnews/vers/bsd42/clsexec.c' <<'END_OF_FILE'
X/*
X * set close on exec (on Berklix)
X */
X
X#include <stdio.h>
X#include <sgtty.h>
X
Xfclsexec(fp)
XFILE *fp;
X{
X (void) ioctl(fileno(fp), FIOCLEX, (char *)NULL);
X}
END_OF_FILE
if test 158 -ne `wc -c <'rnews/vers/bsd42/clsexec.c'`; then
echo shar: \"'rnews/vers/bsd42/clsexec.c'\" unpacked with wrong size!
fi
# end of 'rnews/vers/bsd42/clsexec.c'
fi
if test -f 'rnews/vers/bsd42/fcntl.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/vers/bsd42/fcntl.h'\"
else
echo shar: Extracting \"'rnews/vers/bsd42/fcntl.h'\" \(47 characters\)
sed "s/^X//" >'rnews/vers/bsd42/fcntl.h' <<'END_OF_FILE'
X#include <sys/file.h> /* 4.2's O_EXCL defn */
END_OF_FILE
if test 47 -ne `wc -c <'rnews/vers/bsd42/fcntl.h'`; then
echo shar: \"'rnews/vers/bsd42/fcntl.h'\" unpacked with wrong size!
fi
# end of 'rnews/vers/bsd42/fcntl.h'
fi
if test -f 'rnews/vers/bsd42/memcpy.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/vers/bsd42/memcpy.c'\"
else
echo shar: Extracting \"'rnews/vers/bsd42/memcpy.c'\" \(84 characters\)
sed "s/^X//" >'rnews/vers/bsd42/memcpy.c' <<'END_OF_FILE'
Xmemcpy(to, from, length)
Xchar *to, *from;
Xint length;
X{
X bcopy(from, to, length);
X}
END_OF_FILE
if test 84 -ne `wc -c <'rnews/vers/bsd42/memcpy.c'`; then
echo shar: \"'rnews/vers/bsd42/memcpy.c'\" unpacked with wrong size!
fi
# end of 'rnews/vers/bsd42/memcpy.c'
fi
if test -f 'rnews/vers/usg/clsexec.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/vers/usg/clsexec.c'\"
else
echo shar: Extracting \"'rnews/vers/usg/clsexec.c'\" \(145 characters\)
sed "s/^X//" >'rnews/vers/usg/clsexec.c' <<'END_OF_FILE'
X/*
X * set close on exec (on Uglix)
X */
X
X#include <stdio.h>
X#include <fcntl.h>
X
Xfclsexec(fp)
XFILE *fp;
X{
X (void) fcntl(fileno(fp), F_SETFD, 1);
X}
END_OF_FILE
if test 145 -ne `wc -c <'rnews/vers/usg/clsexec.c'`; then
echo shar: \"'rnews/vers/usg/clsexec.c'\" unpacked with wrong size!
fi
# end of 'rnews/vers/usg/clsexec.c'
fi
if test -f 'rnews/vers/usg/ftime.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/vers/usg/ftime.c'\"
else
echo shar: Extracting \"'rnews/vers/usg/ftime.c'\" \(251 characters\)
sed "s/^X//" >'rnews/vers/usg/ftime.c' <<'END_OF_FILE'
X/*
X * Uglix ftime simulation
X */
X
X#include <sys/types.h>
X#include <sys/timeb.h> /* HACK */
X
Xftime(tp)
Xstruct timeb *tp;
X{
X time_t time();
X
X tp->time = time(&tp->time);
X tp->millitm = 0;
X tp->timezone = 5*60; /* HACK */
X tp->dstflag = 1; /* HACK */
X}
END_OF_FILE
if test 251 -ne `wc -c <'rnews/vers/usg/ftime.c'`; then
echo shar: \"'rnews/vers/usg/ftime.c'\" unpacked with wrong size!
fi
# end of 'rnews/vers/usg/ftime.c'
fi
if test -f 'rnews/vers/v7/clsexec.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/vers/v7/clsexec.c'\"
else
echo shar: Extracting \"'rnews/vers/v7/clsexec.c'\" \(165 characters\)
sed "s/^X//" >'rnews/vers/v7/clsexec.c' <<'END_OF_FILE'
X/*
X * set close on exec (on Unix)
X */
X
X#include <stdio.h>
X#include <sgtty.h>
X
Xfclsexec(fp)
XFILE *fp;
X{
X (void) ioctl(fileno(fp), FIOCLEX, (struct sgttyb *)NULL);
X}
X
END_OF_FILE
if test 165 -ne `wc -c <'rnews/vers/v7/clsexec.c'`; then
echo shar: \"'rnews/vers/v7/clsexec.c'\" unpacked with wrong size!
fi
# end of 'rnews/vers/v7/clsexec.c'
fi
if test -f 'rnews/vers/v7/fcntl.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/vers/v7/fcntl.h'\"
else
echo shar: Extracting \"'rnews/vers/v7/fcntl.h'\" \(0 characters\)
sed "s/^X//" >'rnews/vers/v7/fcntl.h' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'rnews/vers/v7/fcntl.h'`; then
echo shar: \"'rnews/vers/v7/fcntl.h'\" unpacked with wrong size!
fi
# end of 'rnews/vers/v7/fcntl.h'
fi
if test -f 'rnews/vers/v8/README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/vers/v8/README'\"
else
echo shar: Extracting \"'rnews/vers/v8/README'\" \(85 characters\)
sed "s/^X//" >'rnews/vers/v8/README' <<'END_OF_FILE'
XThough it is undocumented, V8 contains an Uglix uname(3) emulation
Xin the C library.
END_OF_FILE
if test 85 -ne `wc -c <'rnews/vers/v8/README'`; then
echo shar: \"'rnews/vers/v8/README'\" unpacked with wrong size!
fi
# end of 'rnews/vers/v8/README'
fi
if test -f 'rnews/zeropad.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'rnews/zeropad.c'\"
else
echo shar: Extracting \"'rnews/zeropad.c'\" \(84 characters\)
sed "s/^X//" >'rnews/zeropad.c' <<'END_OF_FILE'
X/*
X * zero-padding printf format(s) (non-broken)
X */
X
Xchar ldzeropad[] = "%0*.*ld";
END_OF_FILE
if test 84 -ne `wc -c <'rnews/zeropad.c'`; then
echo shar: \"'rnews/zeropad.c'\" unpacked with wrong size!
fi
# end of 'rnews/zeropad.c'
fi
if test -f 'batch/batchmunch' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'batch/batchmunch'\"
else
echo shar: Extracting \"'batch/batchmunch'\" \(566 characters\)
sed "s/^X//" >'batch/batchmunch' <<'END_OF_FILE'
X# Alter batch as appropriate for transmission. Usually this means doing
X# data compression. We explicitly use "-b 12" here because (1) it is the
X# lowest common denominator for news-capable machines, and (2) higher levels
X# of -b are much more expensive in time and memory and seldom yield much
X# denser output.
X#
X# Just 'cat' will do if straight pass-through is desired.
X#
X# The 'echo' is for compatibility with the stupid 2.11 compressed format.
X# The 'exec' cuts down the number of processes active for this simple case.
X
Xecho '#! cunbatch'
Xexec compress -b 12
END_OF_FILE
if test 566 -ne `wc -c <'batch/batchmunch'`; then
echo shar: \"'batch/batchmunch'\" unpacked with wrong size!
fi
# end of 'batch/batchmunch'
fi
if test -f 'batch/roomfor' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'batch/roomfor'\"
else
echo shar: Extracting \"'batch/roomfor'\" \(649 characters\)
sed "s/^X//" >'batch/roomfor' <<'END_OF_FILE'
X# About how many batches of $1 bytes will fit in the available spool space
X# without cramping things too badly?
X#
X# You'll have to change this -- your blocksize, minimum-free-desired amount,
X# and df output format will probably differ, and your spool area may be on
X# a different filesystem.
X
XPATH=/bin:/usr/bin ; export PATH
X
Xmin=15000 # Want to keep this many df blocks free.
Xblock=512 # Size of df block in bytes.
Xavail=`df /dev/usr | awk '{print $2}'` # How much free in spool?
X
Xawk "END {
X nb = int(($avail - $min) * $block / $1)
X if (nb <= 0)
X print 0
X else if (nb > 50) # Arbitrary upper bound.
X print 50
X else
X print nb
X}" /dev/null
END_OF_FILE
if test 649 -ne `wc -c <'batch/roomfor'`; then
echo shar: \"'batch/roomfor'\" unpacked with wrong size!
fi
# end of 'batch/roomfor'
fi
if test -f 'expire/histslash.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'expire/histslash.c'\"
else
echo shar: Extracting \"'expire/histslash.c'\" \(655 characters\)
sed "s/^X//" >'expire/histslash.c' <<'END_OF_FILE'
X/*
X * Convert slashed filenames to dotted group/article names in a history
X * file, for use in mkhistory. Input comes only from stdin.
X */
X#include <stdio.h>
X#include <assert.h>
X
Xchar *progname = "histslash";
X
Xmain()
X{
X char buf[BUFSIZ];
X register char *scan;
X register char *last;
X extern char *strchr();
X
X while (fgets(buf, BUFSIZ, stdin) != NULL) {
X scan = strchr(buf, '\t');
X scan = strchr(scan+1, '\t');
X scan++;
X last = NULL;
X while (*scan != '\0') {
X if (*scan == '/') {
X *scan = '.';
X last = scan;
X }
X if (*scan == ' ' || *scan == '\n') {
X assert(last != NULL);
X *last = '/';
X }
X scan++;
X }
X fputs(buf, stdout);
X }
X}
END_OF_FILE
if test 655 -ne `wc -c <'expire/histslash.c'`; then
echo shar: \"'expire/histslash.c'\" unpacked with wrong size!
fi
# end of 'expire/histslash.c'
fi
## End of shell archive.
exit 0