home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
1
/
1464
< prev
next >
Wrap
Internet Message Format
|
1990-12-28
|
63KB
From: sob@lib.tmc.edu (Stan Barber)
Newsgroups: alt.sources
Subject: rrn/rn combo kit part 7 of 9
Message-ID: <433@lib.tmc.edu>
Date: 14 Jun 90 03:28:56 GMT
#! /bin/sh
# Make a new directory for the rn sources, cd to it, and run kits 1 thru 9
# through sh. When all 9 kits have been run, read README.
echo "This is rn kit 7 (of 9). If kit 7 is complete, the line"
echo '"'"End of kit 7 (of 9)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
echo Extracting help.c
cat >help.c <<'!STUFFY!FUNK!'
/* $Header: help.c,v 4.3.2.1 90/03/22 23:10:10 sob Exp $
*
* $Log: help.c,v $
* Revision 4.3.2.1 90/03/22 23:10:10 sob
* checkpoint
*
* Revision 4.3.1.2 85/09/10 11:05:39 lwall
* Improved %m in in_char().
*
* Revision 4.3.1.1 85/05/10 11:33:10 lwall
* Branch for patches.
*
* Revision 4.3 85/05/01 11:38:59 lwall
* Baseline for release with 4.3bsd.
*
*/
#include "EXTERN.h"
#include "common.h"
#include "rn.h"
#include "term.h"
#include "INTERN.h"
#include "help.h"
void
help_init()
{
;
}
int
help_page()
{
int cmd;
#ifdef PAGERHELP
doshell(sh,filexp(PAGERHELP));
#else
page_init();
if ((cmd = print_lines("\
Paging commands:\n\
",STANDOUT)) ||
(cmd = print_lines("\n\
SP Display the next page.\n\
x Display the next page decrypted (rot13).\n\
d Display half a page more.\n\
CR Display one more line.\n\
^R,v,^X Restart the current article (v=verbose header, ^X=rot13).\n\
",NOMARKING)) ||
(cmd = print_lines("\
^B Back up one page.\n\
^L,X Refresh the screen (X=rot13).\n\
g pat Go to (search forward within article for) pattern.\n\
G Search again for current pattern within article.\n\
^G Search for next line beginning with \"Subject:\".\n\
TAB Search for next line beginning with a different character.\n\
q Quit the pager, go to end of article. Leave article read or unread.\n\
j Junk this article (mark it read). Goes to end of article.\n\
\n\
",NOMARKING)) ||
(cmd = print_lines("\
The following commands skip the rest of the current article, then behave\n\
just as if typed to the 'What next?' prompt at the end of the article:\n\
",STANDOUT)) ||
(cmd = print_lines("\n\
n Scan forward for next unread article.\n\
N Go to next article.\n\
^N Scan forward for next unread article with same title.\n\
p,P,^P Same as n,N,^N, only going backwards.\n\
- Go to previously displayed article.\n\
\n\
",NOMARKING)) ||
(cmd = print_lines("\
The following commands also take you to the end of the article.\n\
Type h at end of article for a description of these commands:\n\
",STANDOUT)) ||
(cmd = print_lines("\
# $ & / = ? c C f F k K ^K m M number r R ^R s S u v w W Y ^ |\n\
\n\
(To return to the middle of the article after one of these commands, type ^L.)\n\
",NOMARKING)) )
return cmd;
#endif
return 0;
}
int
help_art()
{
int cmd;
#ifdef ARTHELP
doshell(sh,filexp(ARTHELP));
#else
page_init();
if ((cmd = print_lines("\
Article Selection commands:\n\
",STANDOUT)) ||
(cmd = print_lines("\n\
n,SP Scan forward for next unread article.\n\
N Go to next article.\n\
^N Scan forward for next unread article with same subject.\n\
p,P,^P Same as n,N,^N, only going backwards.\n\
- Go to previously displayed article.\n\
",NOMARKING)) ||
(cmd = print_lines("\
number Go to specified article.\n\
range{,range} command{:command}\n\
Apply one or more commands to one or more ranges of articles.\n\
Ranges are of the form: number | number-number. You may use . for\n\
the current article, and $ for the last article.\n\
Valid commands are: j, m, M, s, S, and !.\n\
",NOMARKING)) ||
(cmd = print_lines("\
/pattern/modifiers\n\
Scan forward for article containing pattern in the subject line.\n\
(Use ?pat? to scan backwards; append h to scan headers, a to scan\n\
entire articles, r to scan read articles, c to make case sensitive.\n\
/pattern/modifiers:command{:command}\n\
Apply one or more commands to the set of articles matching pattern.\n\
Use a K modifier to save entire command to the KILL file for this\n\
newsgroup. Commands m and M, if first, imply an r modifier.\n\
Valid commands are: j, m, M, s, S, and !.\n\
",NOMARKING)) ||
(cmd = print_lines("\
f,F Submit a followup article (F = include this article).\n\
r,R Reply through net mail (R = include this article).\n\
s ... Save to file or pipe via sh.\n\
S ... Save via preferred shell.\n\
w,W Like s and S but save without the header.\n\
| ... Same as s|...\n\
C Cancel this article, if yours.\n\
",NOMARKING)) ||
(cmd = print_lines("\
^R,v Restart article (v=verbose).\n\
^X Restart article, rot13 mode.\n\
c Catch up (mark all articles as read).\n\
^B Back up one page.\n\
^L Refresh the screen. You can get back to the pager with this.\n\
X Refresh screen in rot13 mode.\n\
",NOMARKING)) ||
(cmd = print_lines("\
^ Go to first unread article. Disables subject search mode.\n\
$ Go to end of newsgroup. Disables subject search mode.\n\
",NOMARKING)) ||
(cmd = print_lines("# Print last article number.\n\
& Print current values of command-line switches.\n\
&switch {switch}\n\
Set or unset more switches.\n\
&& Print current macro definitions.\n\
&&def Define a new macro.\n\
j Junk this article (mark it read). Stays at end of article.\n\
m Mark article as still unread.\n\
M Mark article as still unread upon exiting newsgroup or Y command.\n\
",NOMARKING)) ||
(cmd = print_lines("\
Y Yank back articles marked temporarily read via M.\n\
k Mark current SUBJECT as read.\n\
K Mark current SUBJECT as read, and save command in KILL file.\n\
= List subjects of unread articles.\n\
u Unsubscribe to this newsgroup.\n\
^K Edit local KILL file (the one for this newsgroup).\n\
q Quit this newsgroup for now.\n\
Q Quit newsgroup, staying at current newsgroup.\n\
",NOMARKING)) )
return cmd;
#endif
return 0;
}
int
help_ng()
{
int cmd;
#ifdef NGHELP
doshell(sh,filexp(NGHELP));
#else
page_init();
if (cmd = print_lines("\
Newsgroup Selection commands:\n\
",STANDOUT) )
return cmd;
if (ng != nextrcline) {
if (cmd = print_lines("\
\n\
y,SP Do this newsgroup now.\n\
.cmd Do this newsgroup, executing cmd as first command.\n\
= Equivalent to .=<carriage return>.\n\
u Unsubscribe from this newsgroup.\n\
c Catch up (mark this newsgroup all read).\n\
",NOMARKING) )
return cmd;
}
if ((cmd = print_lines("\
\n\
n Go to the next newsgroup with unread news.\n\
N Go to the next newsgroup.\n\
p Go to the previous newsgroup with unread news.\n\
P Go to the previous newsgroup.\n\
",NOMARKING)) ||
(cmd = print_lines("\
- Go to the previously displayed newsgroup.\n\
1 Go to the first newsgroup.\n\
^ Go to the first newsgroup with unread news.\n\
$ Go to the last newsgroup.\n\
",NOMARKING)) ||
(cmd = print_lines("\
g name Go to the named newsgroup. Subscribe to new newsgroups this way too.\n\
/pat Search forward for newsgroup matching pattern.\n\
?pat Search backward for newsgroup matching pattern.\n\
(Use * and ? style patterns. Append r to include read newsgroups.)\n\
",NOMARKING)) ||
(cmd = print_lines("\
l pat List unsubscribed newsgroups containing pattern.\n\
m name Move named newsgroup elsewhere (no name moves current newsgroup).\n\
o pat Only display newsgroups matching pattern. Omit pat to unrestrict.\n\
a pat Like o, but also scans for unsubscribed newsgroups matching pattern.\n\
L List current .newsrc.\n\
",NOMARKING)) ||
(cmd = print_lines("\
& Print current command-line switch settings.\n\
&switch {switch}\n\
Set (or unset) more command-line switches.\n\
&& Print current macro definitions.\n\
&&def Define a new macro.\n\
!cmd Shell escape.\n\
",NOMARKING)) ||
(cmd = print_lines("\
q Quit rn.\n\
^K Edit the global KILL file. Use commands like /pattern/j to suppress\n\
pattern in every newsgroup.\n\
v Print version.\n\
",NOMARKING)) )
return cmd;
#endif
#ifdef PUSHBACK
if (cmd = get_anything())
return cmd;
show_macros();
#endif
return 0;
}
#ifdef ESCSUBS
int
help_subs()
{
int cmd;
#ifdef SUBSHELP
doshell(sh,filexp(SUBSHELP));
#else
page_init();
if ((cmd = print_lines("\
Valid substitutions are:\n\
",STANDOUT)) ||
(cmd = print_lines("\
\n\
a Current article number\n\
A Full name of current article (%P/%c/%a)\n\
b Destination of last save command, often a mailbox\n\
B Bytes to ignore at beginning of last saved article\n\
",NOMARKING)) ||
(cmd = print_lines("\
c Current newsgroup, directory form\n\
C Current newsgroup, dot form\n\
d Full name of newsgroup directory (%P/%c)\n\
D Distribution line from current article\
",NOMARKING)) ||
(cmd = print_lines("\
f Who the current article is from\n\
F Newsgroups to followup to (from Newsgroups and Followup-To)\n\
h (This help message)\n\
H Host name (yours)\n\
i Message-I.D. line from current article, with <>\n\
I Reference indicator mark (see -F switch)\n\
",NOMARKING)) ||
(cmd = print_lines("\
l News administrator's login name, if any\n\
L Login name (yours)\n\
m Current mode, first letter of (init, newsgroup, article, pager,\n\
Add, Catchup, Delete bogus, Mailbox, Resubscribe)\n\
M Number of article marked with M\n\
n Newsgroups from current article\n\
N Full name (yours)\n\
",NOMARKING)) ||
(cmd = print_lines("\
o Organization (yours)\n\
O Original working directory (where you ran rn from)\n\
p Your private news directory (from -d)\n\
P Public news spool directory\n\
",NOMARKING)) ||
(cmd = print_lines("\
r Last reference (parent article id)\n\
R References list for followup article\n\
s Subject, with all Re's and (nf)'s stripped off\n\
S Subject, with one Re stripped off\
",NOMARKING)) ||
(cmd = print_lines("\
t New To line derived from From and Reply-To (Internet format)\n\
T New To line derived from Path\n\
u Number of unread articles\n\
U Number of unread articles not counting current article\n\
x News library directory\n\
X Rn library directory\n\
z Length of current article in bytes\n\
",NOMARKING)) ||
(cmd = print_lines("\
~ Your home directory\n\
. Directory containing . files\n\
$ Current process number\n\
/ Last search string\n\
ESC Run preceding command through % interpretation\n\
",NOMARKING)) )
return cmd;
#endif
return 0;
}
#endif
!STUFFY!FUNK!
echo Extracting head.c
cat >head.c <<'!STUFFY!FUNK!'
/* $Header: head.c,v 4.3.2.5 90/03/22 23:04:22 sob Exp $
*
* $Log: head.c,v $
* Revision 4.3.2.5 90/03/22 23:04:22 sob
* Fixes provided by Wayne Davison <drivax!davison>
*
* Revision 4.3.2.4 89/11/27 01:30:35 sob
* Altered NNTP code per ideas suggested by Bela Lubkin
* <filbo@gorn.santa-cruz.ca.us>
*
* Revision 4.3.2.3 89/11/26 22:53:52 sob
* Add new patches to make RRN be faster.
*
* Revision 4.3.2.2 89/11/08 01:17:46 sob
* Added changes to insure that this will compile for RN or RRN with no
* changes to the source code.
*
* Revision 4.3.2.1 89/11/06 00:37:18 sob
* Added RRN support from NNTP 1.5
*
* Revision 4.3.1.2 85/05/10 13:47:25 lwall
* Added debugging stuff.
*
* Revision 4.3.1.1 85/05/10 11:32:30 lwall
* Branch for patches.
*
* Revision 4.3 85/05/01 11:38:21 lwall
* Baseline for release with 4.3bsd.
*
*/
#include "EXTERN.h"
#include "common.h"
#include "artio.h"
#include "bits.h"
#ifdef SERVER
#include "server.h"
#endif
#include "util.h"
#include "INTERN.h"
#include "head.h"
bool first_one; /* is this the 1st occurance of this header line? */
static char htypeix[26] =
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void
head_init()
{
register int i;
for (i=HEAD_FIRST+1; i<HEAD_LAST; i++)
htypeix[*htype[i].ht_name - 'a'] = i;
}
#ifdef DEBUGGING
dumpheader(where)
char *where;
{
register int i;
printf("header: %d %s", parsed_art, where);
for (i=0; i<HEAD_LAST; i++) {
printf("%15s %4d %4d %03o\n",htype[i].ht_name,
htype[i].ht_minpos,
htype[i].ht_maxpos,
htype[i].ht_flags) FLUSH;
}
}
#endif
int
set_line_type(bufptr,colon)
char *bufptr;
register char *colon;
{
char lc[LONGKEY+3];
register char *t, *f;
register int i, len;
if (colon-bufptr > LONGKEY+2)
return SOME_LINE;
for (t=lc,f=bufptr; f<colon; f++, t++) {
if (isspace(*f))
/* guard against space before : */
break;
*t = isupper(*f) ? tolower(*f) : *f;
}
*t = '\0';
f = lc; /* get lc into register */
len = t - f;
/* now scan the headtype table, backwards so we don't have to supply an
* extra terminating value, using first letter as index, and length as
* optimization to avoid calling subroutine strEQ unnecessarily. Hauls.
*/
if (islower(*f)) {
for (i = htypeix[*f - 'a']; *htype[i].ht_name == *f; --i) {
if (len == htype[i].ht_length && strEQ(f, htype[i].ht_name)) {
return i;
}
}
}
return SOME_LINE;
}
void
start_header(artnum)
ART_NUM artnum;
{
register int i;
#ifdef DEBUGGING
if (debug & 4)
dumpheader("start_header\n");
#endif
for (i=0; i<HEAD_LAST; i++) {
htype[i].ht_minpos = -1;
htype[i].ht_maxpos = 0;
}
in_header = SOME_LINE;
first_one = FALSE;
#ifdef ASYNC_PARSE
parsed_art = artnum;
#endif
}
bool
parseline(art_buf,newhide,oldhide)
char *art_buf;
int newhide, oldhide;
{
if (*art_buf == ' ' || *art_buf == '\t')
/* header continuation line? */
return oldhide;
else { /* maybe another header line */
char *s;
if (first_one) { /* did we just pass 1st occurance? */
first_one = FALSE;
htype[in_header].ht_maxpos = artpos;
/* remember where line left off */
}
s = index(art_buf,':');
if (s == Nullch) {
/* is it the end of the header? */
htype[PAST_HEADER].ht_minpos =
(*art_buf == '\n') ? ftell(artfp) : artpos;
/* remember where body starts */
in_header = PAST_HEADER;
}
else { /* it is a new header line */
in_header = set_line_type(art_buf,s);
first_one = (htype[in_header].ht_minpos < 0);
if (first_one)
htype[in_header].ht_minpos = artpos;
#ifdef DEBUGGING
if (debug & 4)
dumpheader(art_buf);
#endif
if (htype[in_header].ht_flags & HT_HIDE)
return newhide;
}
}
return FALSE; /* don't hide this line */
}
#ifdef ASYNC_PARSE
int
parse_maybe(artnum)
ART_NUM artnum;
{
char tmpbuf[LBUFLEN];
if (parsed_art == artnum)
return 0;
/* no maybe about it now */
#ifdef SERVER
if (nntpopen(artnum,HEAD) == Nullfp) {
#else
if (artopen(artnum) == Nullfp) {
#endif
return -1;
}
start_header(artnum);
while (in_header) {
artpos = ftell(artfp);
if (fgets(tmpbuf,LBUFLEN,artfp) == Nullch)
break;
parseline(tmpbuf,FALSE,FALSE);
}
in_header = PAST_HEADER;
return 0;
}
#endif
/* get the subject line for an article */
char *
fetchsubj(artnum,current_subject,copy)
ART_NUM artnum; /* article to get subject from */
bool current_subject; /* is it in a parsed header? */
bool copy; /* do you want it savestr()ed? */
{
char *s = Nullch, *t;
#ifdef SERVER
static int xhdr = 1; /* Can we use xhdr command? */
int eoo; /* End of server output */
char ser_line[256];
#endif SERVER
#ifdef CACHESUBJ
if (!subj_list) {
register ART_NUM i;
#ifndef lint
subj_list =
(char**)safemalloc((MEM_SIZE)((OFFSET(lastart)+2)*sizeof(char *)));
#endif lint
for (i=0; i<=OFFSET(lastart); i++)
subj_list[i] = Nullch;
}
if (!artnum || artnum > lastart)
s = nullstr;
else
s = subj_list[OFFSET(artnum)];
#endif
if (s == Nullch) {
if (current_subject) {
s = fetchlines(artnum,SUBJ_LINE);
#ifdef CACHESUBJ
subj_list[OFFSET(artnum)] = s;
#endif
}
else {
s = safemalloc((MEM_SIZE)256);
*s = '\0';
#ifdef SERVER
if (xhdr) {
sprintf(ser_line, "XHDR subject %ld", artnum);
put_server(ser_line);
if (get_server(ser_line, sizeof (ser_line)) >= 0) {
if (ser_line[0] == CHAR_FATAL) {
xhdr = 0;
} else {
while (get_server(ser_line, sizeof (ser_line)) >= 0) {
if (ser_line[0] == '.')
break;
else {
t = index(ser_line, ' ');
if (t++) {
strcpy(s, t);
if (t = index(s, '\r'))
*t = '\0';
}
}
}
}
} else {
fprintf(stderr,
"rrn: Unexpected close of server socket.\n");
finalize(1);
}
}
if (!xhdr) {
sprintf(ser_line, "HEAD %ld", artnum);
put_server(ser_line);
eoo = 0;
if (get_server(ser_line, 256) >= 0 && ser_line[0] == CHAR_OK) {
do {
if (get_server(s, 256) < 0 || (*s == '.')) {
strcpy(s, "Title: \n");
eoo = 1;
}
} while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
if (!eoo)
while (get_server(ser_line, sizeof (ser_line)) >= 0 &&
ser_line[0] != '.');
t = index(s,':')+1;
while (*t == ' ') t++;
strcpy(s, t);
}
}
#else not SERVER
if (artopen(artnum) != Nullfp) {
do {
if (fgets(s,256,artfp) == Nullch)
strcpy(s, "Title: \n");
} while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
s[strlen(s)-1] = '\0';
t = index(s,':')+1;
while (*t == ' ') t++;
strcpy(s, t);
}
#endif
s = saferealloc(s, (MEM_SIZE)strlen(s)+1);
#ifdef CACHESUBJ
subj_list[OFFSET(artnum)] = s;
#endif
}
}
#ifdef CACHESUBJ
if (copy) {
t = savestr(s);
return t;
}
else
return s;
#else
if (copy)
return s;
else {
safecpy(cmd_buf,s,CBUFLEN); /* hope this is okay--we're */
free(s);
return cmd_buf; /* really scraping for space here */
}
#endif
}
/* get header lines from an article */
char *
fetchlines(artnum,which_line)
ART_NUM artnum; /* article to get line from */
int which_line; /* type of line desired */
{
char *newbuf, *t, tmp_buf[LBUFLEN];
register ART_POS curpos;
int size;
register ART_POS firstpos;
register ART_POS lastpos;
#ifdef ASYNC_PARSE
if (parse_maybe(artnum))
artnum = 0;
#endif
firstpos = htype[which_line].ht_minpos;
lastpos = htype[which_line].ht_maxpos;
#ifdef SERVER
if (!artnum || firstpos < 0 || nntpopen(artnum,HEAD) == Nullfp) {
#else
if (!artnum || firstpos < 0 || artopen(artnum) == Nullfp) {
#endif
newbuf = safemalloc((unsigned int)1);
*newbuf = '\0';
return newbuf;
}
#ifndef lint
size = lastpos - firstpos + 1;
#else
size = Null(int);
#endif lint
#ifdef DEBUGGING
if (debug && (size < 1 || size > 1000)) {
printf("Firstpos = %ld, lastpos = %ld\n",(long)firstpos,(long)lastpos);
gets(tmp_buf);
}
#endif
newbuf = safemalloc((unsigned int)size);
*newbuf = '\0';
fseek(artfp,firstpos,0);
for (curpos = firstpos; curpos < lastpos; curpos = ftell(artfp)) {
if (fgets(tmp_buf,LBUFLEN,artfp) == Nullch)
break;
if (*tmp_buf == ' ' || *tmp_buf == '\t')
t = tmp_buf;
else
t = index(tmp_buf,':')+1;
if (t == Nullch)
break;
else {
while (*t == ' ' || *t == '\t') t++;
safecat(newbuf,t,size);
}
}
return newbuf;
}
!STUFFY!FUNK!
echo Extracting init.c
cat >init.c <<'!STUFFY!FUNK!'
/* $Header: init.c,v 4.3.2.6 90/05/08 22:05:55 sob Exp $
*
* $Log: init.c,v $
* Revision 4.3.2.6 90/05/08 22:05:55 sob
* Added quick startup (-q) flag.
*
* Revision 4.3.2.5 90/05/04 23:10:01 sob
* Fix for exiting "second" rn such that tty will be left in correct state.
* Provided by glenn@mathcs.emory.edu
*
* Revision 4.3.2.4 90/03/22 23:04:32 sob
* Fixes provided by Wayne Davison <drivax!davison>
*
* Revision 4.3.2.3 90/03/17 21:34:04 sob
* Cleaned up a bit.
*
* Revision 4.3.2.2 89/11/08 01:17:48 sob
* Added changes to insure that this will compile for RN or RRN with no
* changes to the source code.
*
* Revision 4.3.2.1 89/11/06 00:39:14 sob
* Added RRN support from NNTP 1.5
*
* Revision 4.3.1.4 86/09/05 14:24:02 lwall
* Removed net.announce dependency.
*
* Revision 4.3.1.3 85/07/23 18:08:36 lwall
* Fixed up NOLINEBUF option to work.
*
* Revision 4.3.1.2 85/05/21 14:22:46 lwall
* Sped up "rn -c" by avoiding unnecessary initialization.
*
* Revision 4.3.1.1 85/05/10 11:33:39 lwall
* Branch for patches.
*
* Revision 4.3 85/05/01 16:16:13 lwall
* Baseline for release with 4.3bsd.
*
*/
#include "EXTERN.h"
#include "common.h"
#include "util.h"
#include "final.h"
#include "term.h"
#include "last.h"
#include "rn.h"
#include "rcstuff.h"
#include "ngdata.h"
#include "only.h"
#include "intrp.h"
#include "addng.h"
#include "sw.h"
#include "art.h"
#include "artsrch.h"
#include "artio.h"
#include "backpage.h"
#include "bits.h"
#include "cheat.h"
#include "head.h"
#include "help.h"
#include "kfile.h"
#include "ngsrch.h"
#include "ngstuff.h"
#include "rcln.h"
#include "respond.h"
#ifdef SERVER
#include "server.h"
#endif
#include "ng.h"
#include "INTERN.h"
#include "init.h"
bool
initialize(argc,argv)
int argc;
char *argv[];
{
char *tcbuf;
register bool foundany = FALSE;
long time();
#ifdef SERVER
char *server;
int response;
#endif SERVER
#ifdef NOLINEBUF
static char std_out_buf[BUFSIZ]; /* must be static or malloced */
setbuf(stdout, std_out_buf);
#endif
tcbuf = safemalloc(1024); /* make temp buffer for termcap and */
/* other initialization stuff */
/* init terminal */
term_init(); /* must precede sw_init() so that */
/* ospeed is set for baud-rate */
/* switches. Actually terminal */
/* mode setting is in term_set() */
/* we have to know rnlib to look up global switches in %X/INIT */
lib = savestr(filexp(LIB));
rnlib = savestr(filexp(RNLIB));
/* decode switches */
sw_init(argc,argv,&tcbuf); /* must not do % interps! */
/* (but may mung environment) */
/* init signals, status flags */
final_init();
/* start up file expansion and the % interpreter */
intrp_init(tcbuf);
/* now make sure we have a current working directory */
if (!checkflag)
cwd_check();
/* now that we know where to save things, cd to news directory */
if (chdir(spool)) {
printf(nocd,spool) FLUSH;
finalize(1);
}
/* if we aren't just checking, turn off echo */
if (!checkflag)
term_set(tcbuf);
/* get info on last rn run, if any */
if (!checkflag)
last_init(tcbuf);
free(tcbuf); /* recover 1024 bytes */
/* make sure we are the sole possessors of .newsrc */
if (!checkflag)
lock_check();
/* check for news news */
if (!checkflag)
newsnews_check();
#ifdef SERVER
/* open connection to server if appropriate */
server = getserverbyfile(SERVER_FILE);
if (server == NULL) {
fprintf(stderr, "Can't get the name of the news server from %s\n",
SERVER_FILE);
fprintf(stderr,
"Either fix this file, or put NNTPSERVER in your environment.\n");
finalize(1);
}
response = server_init(server);
if (response < 0) {
fprintf(stderr,
"Couldn't connect to %s news server, try again later.\n",
server);
finalize(1);
}
if (handle_server_response(response, server) < 0)
finalize(1);
#endif SERVER
/* open active file, etc. */
ngdata_init();
/* now read in the .newsrc file */
foundany = rcstuff_init();
/* it looks like we will actually read something, so init everything */
addng_init();
art_init();
artio_init();
artsrch_init();
backpage_init();
bits_init();
cheat_init();
head_init();
help_init();
kfile_init();
ng_init();
ngsrch_init();
ngstuff_init();
only_init();
rcln_init();
respond_init();
rn_init();
search_init();
util_init();
#ifdef FINDNEWNG
fstat(actfp->_file,&filestat); /* did active file grow? */
/*
* Skip this check if the -q flag was given.
*/
if (!quickstart && filestat.st_size != lastactsiz) {
long actsiz = filestat.st_size; /* remember new size */
NG_NUM oldnext = nextrcline; /* remember # lines in newsrc */
#ifdef FASTNEW
bool munged = writesoft || !lastactsiz;
/* bad soft ptrs -> edited active */
#else
bool munged = TRUE; /* just assume .newsrc munged */
#endif
#ifdef VERBOSE
IF(verbose)
fputs("\nChecking active list for new newsgroups...\n",stdout)
FLUSH;
ELSE
#endif
#ifdef TERSE
fputs("\nNew newsgroups:\n",stdout) FLUSH;
#endif
#ifdef FASTNEW
if (!munged) { /* maybe just do tail of file? */
fseek(actfp,lastactsiz-1,0);
fgets(buf,LBUFLEN,actfp);
munged = (*buf != '\n');
if (!munged)
munged = newlist(munged,FALSE);
}
#endif
if (munged) { /* must we scan entire file? */
fseek(actfp,0L,0); /* rewind active file */
newlist(munged,FALSE); /* sure hope they use hashing... */
}
lastactsiz = actsiz; /* remember for .rnlast */
if (nextrcline != oldnext) { /* did we add any new groups? */
foundany = TRUE; /* let main() know */
starthere = 0; /* and start ng scan from the top */
}
}
#endif
time(&lasttime); /* remember when we inited-- */
/* ends up back in .rnlast */
writelast(); /* in fact, put it there now */
#ifdef FINDNEWNG
# ifdef ONLY
if (maxngtodo) /* patterns on command line? */
foundany |= scanactive();
# endif
#endif
return foundany;
}
/* make sure there is no rn out there already */
void
lock_check()
{
lockname = savestr(filexp(LOCKNAME));
if (!checkflag) {
tmpfp = fopen(lockname,"r");
if (tmpfp != Nullfp) {
int processnum;
fgets(buf,LBUFLEN,tmpfp);
fclose(tmpfp);
processnum = atoi(buf);
#ifdef VERBOSE
IF(verbose)
printf("You seem to have left an rn running, process %d.\n",
processnum) FLUSH;
ELSE
#endif
#ifdef TERSE
printf("Rn left running, #%d.\n", processnum) FLUSH;
#endif
if (kill(processnum, SIGEMT)) {
/* does process not exist? */
/* (rn ignores SIGEMT) */
sleep(2);
#ifdef VERBOSE
IF(verbose)
fputs("\n\
That process does not seem to exist anymore. The count of read articles\n\
may be incorrect in the last newsgroup accessed by that other (defunct)\n\
process.\n\n",stdout) FLUSH;
ELSE
#endif
#ifdef TERSE
fputs("\nProcess crashed.\n",stdout) FLUSH;
#endif
if (*lastngname) {
#ifdef VERBOSE
IF(verbose)
printf("(The last newsgroup accessed was %s.)\n\n",
lastngname) FLUSH;
ELSE
#endif
#ifdef TERSE
printf("(In %s.)\n\n",lastngname) FLUSH;
#endif
}
get_anything();
putchar('\n') FLUSH;
}
else {
#ifdef VERBOSE
IF(verbose)
fputs("\n\
You may not have two copies of rn running simultaneously. Goodbye.\n\
",stdout) FLUSH;
ELSE
#endif
#ifdef TERSE
fputs("\nCan't start another.\n",stdout) FLUSH;
#endif
if (bizarre)
resetty();
exit(0);
}
}
tmpfp = fopen(lockname,"w");
if (tmpfp == Nullfp) {
printf(cantcreate,lockname) FLUSH;
sig_catcher(0);
}
fprintf(tmpfp,"%d\n",getpid());
fclose(tmpfp);
}
}
void
newsnews_check()
{
char *newsnewsname = filexp(NEWSNEWSNAME);
if ((tmpfp = fopen(newsnewsname,"r")) != Nullfp) {
fstat(tmpfp->_file,&filestat);
if (filestat.st_mtime > lasttime) {
while (fgets(buf,sizeof(buf),tmpfp) != Nullch)
fputs(buf,stdout) FLUSH;
get_anything();
putchar('\n') FLUSH;
}
fclose(tmpfp);
}
}
!STUFFY!FUNK!
echo Extracting ngdata.c
cat >ngdata.c <<'!STUFFY!FUNK!'
/* $Header: ngdata.c,v 4.3.2.10 90/04/14 22:05:15 sob Exp $
*
* $Log: ngdata.c,v $
* Revision 4.3.2.10 90/04/14 22:05:15 sob
* Removed redundant declaration of active_name
*
* Revision 4.3.2.9 90/03/22 23:04:55 sob
* Fixes provided by Wayne Davison <drivax!davison>
*
* Revision 4.3.2.8 90/03/17 20:50:51 sob
* Fixes provided by stewart@netxcom.iad-nxe.global-mis.dhl.com to handle
* flaky transfers of the active file from the server.
*
* Revision 4.3.2.7 90/03/17 17:11:08 sob
* Added support for CNEWS active file flags.
*
* Revision 4.3.2.6 89/12/08 22:42:04 sob
* Corrected typo in an #ifdef statement pointed out by
* jik@pit-manager.mit.edu
*
* Revision 4.3.2.5 89/11/28 01:51:14 sob
* Removed redundant #include directive.
*
* Revision 4.3.2.4 89/11/27 01:31:07 sob
* Altered NNTP code per ideas suggested by Bela Lubkin
* <filbo@gorn.santa-cruz.ca.us>
*
* Revision 4.3.2.3 89/11/08 02:41:40 sob
* Removed unneeded subroutine.
*
* Revision 4.3.2.2 89/11/08 02:24:31 sob
* Integrated modifications from other RRN patches colleceted from USENET
*
* Revision 4.3.2.1 89/11/06 00:42:43 sob
* Added RRN support from NNTP 1.5
*
* Revision 4.3 85/05/01 11:44:38 lwall
* Baseline for release with 4.3bsd.
*
*/
#include "EXTERN.h"
#include "common.h"
#include "ndir.h"
#include "rcstuff.h"
#include "rn.h"
#include "intrp.h"
#include "final.h"
#include "rcln.h"
#include "util.h"
#ifdef SERVER
#include "server.h"
#endif
#include "INTERN.h"
#include "ngdata.h"
void
ngdata_init()
{
#ifdef SERVER
char ser_line[256];
char *cp;
int entries;
#endif
/* The following is only for systems that do not zero globals properly */
#ifdef ZEROGLOB
# ifdef CACHEFIRST
for (i=0; i<MAXRCLINE; i++)
abs1st[i] = 0;
# endif
#endif /* ZEROGLOB */
/* open the active file */
#ifdef SERVER
put_server("LIST"); /* tell server we want the active file */
get_server(ser_line, sizeof(ser_line));
if (*ser_line != CHAR_OK) { /* and then see if that's ok */
fprintf(stdout, "Can't get active file from server: \n%s\n", ser_line);
finalize(1);
}
cp = filexp("/tmp/rrnact.%$"); /* make a temporary name */
strcpy(active_name, cp);
actfp = fopen(active_name, "w+"); /* and get ready */
if (actfp == Nullfp) {
printf(cantopen,active_name) FLUSH;
finalize(1);
}
entries = 0;
while (1) {
if (get_server(ser_line, sizeof(ser_line)) < 0) {
printf("Can't get active file from server:\ntransfer failed after %d entries\n", entries);
finalize(1);
}
if (ser_line[0] == '.') /* while there's another line */
break; /* get it and write it to */
entries++;
fputs(ser_line, actfp);
putc('\n', actfp);
}
fseek(actfp,0L,0); /* just get to the beginning */
#else not SERVER
actfp = fopen(filexp(ACTIVE),"r");
if (actfp == Nullfp) {
printf(cantopen,filexp(ACTIVE)) FLUSH;
finalize(1);
}
#endif SERVER
}
/* find the maximum article number of a newsgroup */
ART_NUM
getngsize(num)
register NG_NUM num;
{
register int len;
register char *nam;
char tmpbuf[80];
ART_POS oldsoft;
nam = rcline[num];
len = rcnums[num] - 1;
softtries++;
#ifdef DEBUGGING
if (debug & DEB_SOFT_POINTERS)
printf("Softptr = %ld\n",(long)softptr[num]) FLUSH;
#endif
oldsoft = softptr[num];
if ((softptr[num] = findact(tmpbuf, nam, len, (long)oldsoft)) >= 0) {
if (softptr[num] != oldsoft) {
softmisses++;
writesoft = TRUE;
}
}
else {
softptr[num] = 0;
if (rcchar[num] == ':') /* unsubscribe quietly */
rcchar[num] = NEGCHAR;
return TR_BOGUS; /* well, not so quietly, actually */
}
#ifdef DEBUGGING
if (debug & DEB_SOFT_POINTERS) {
printf("Should be %ld\n",(long)softptr[num]) FLUSH;
}
#endif
#ifdef MININACT
{
register char *s;
ART_NUM tmp;
for (s=tmpbuf+len+1; isdigit(*s); s++) ;
if (tmp = atol(s))
#ifdef CACHEFIRST
abs1st[num] = tmp;
#else
abs1st = tmp;
#endif
if (!in_ng) {
for (s++; isdigit(*s); s++) ;
while (isspace(*s)) s++;
switch (*s) {
case 'n': moderated = getval("NOPOSTRING"," (no posting)"); break;
case 'm': moderated = getval("MODSTRING", " (moderated)"); break;
/* This shouldn't even occur. What are we doing in a non-existent
group? Disallow it. */
case 'x': return TR_BOGUS;
/* what should be done about refiled groups? rn shouldn't even
be in them (ie, if sci.aquaria is refiled to rec.aquaria, then
get the news there) */
case '=': return TR_BOGUS;
default: moderated = nullstr;
}
}
}
#endif
return atol(tmpbuf+len+1);
}
ACT_POS
findact(outbuf,nam,len,suggestion)
char *outbuf;
char *nam;
int len;
long suggestion;
{
ACT_POS retval;
fseek(actfp,100000L,1); /* hopefully this forces a reread */
if (suggestion == 0L || fseek(actfp,suggestion,0) < 0 ||
fgets(outbuf,80,actfp) == Nullch ||
outbuf[len] != ' ' ||
strnNE(outbuf,nam,len)) {
#ifdef DEBUGGING
if (debug & DEB_SOFT_POINTERS)
printf("Missed, looking for %s in %sLen = %d\n",nam,outbuf,len)
FLUSH;
#endif
fseek(actfp,0L,0);
#ifndef lint
retval = (ACT_POS)ftell(actfp);
#else
retval = Null(ACT_POS);
#endif lint
while (fgets(outbuf,80,actfp) != Nullch) {
if (outbuf[len] == ' ' && strnEQ(outbuf,nam,len))
return retval;
#ifndef lint
retval = (ACT_POS) ftell(actfp);
#endif lint
}
return (ACT_POS) -1; /* well, not so quietly, actually */
}
else
#ifndef lint
return (ACT_POS) suggestion;
#else
return retval;
#endif lint
/*NOTREACHED*/
}
/* determine the absolutely first existing article number */
#ifdef SERVER
ART_NUM
getabsfirst(ngnum,ngsize)
register NG_NUM ngnum;
ART_NUM ngsize;
{
register ART_NUM a1st;
#ifndef MININACT
char ser_line[256];
ART_NUM x,y;
#endif
#ifdef CACHEFIRST
if (a1st = abs1st[ngnum])
return a1st;
#endif
#ifdef MININACT
getngsize(ngnum);
# ifdef CACHEFIRST
return abs1st[ngnum];
# else
return abs1st;
# endif
#else
sprintf(cp,"GROUP %s",rcline[ngnum]);
put_server(cp);
if (get_server(ser_line, sizeof(ser_line)) < 0) {
fprintf(stderr, "rrn: Unexpected close of server socket.\n");
finalize(1);
}
if (*ser_line != CHAR_OK) { /* and then see if that's ok */
a1st = ngsize+1; /* nothing there */
}
(void) sscanf(ser_line,"%d%d%d",&x,&y,&a1st);
# ifdef CACHEFIRST
abs1st[ngnum] = a1st;
# endif
return a1st;
#endif
}
/* we already know the lowest article number with NNTP */
ART_NUM
getngmin(dirname,floor)
char *dirname;
ART_NUM floor;
{
return(floor);
}
#else
ART_NUM
getabsfirst(ngnum,ngsize)
register NG_NUM ngnum;
ART_NUM ngsize;
{
register ART_NUM a1st;
#ifndef MININACT
char dirname[MAXFILENAME];
#endif
#ifdef CACHEFIRST
if (a1st = abs1st[ngnum])
return a1st;
#endif
#ifdef MININACT
getngsize(ngnum);
# ifdef CACHEFIRST
return abs1st[ngnum];
# else
return abs1st;
# endif
#else not MININACT
sprintf(dirname,"%s/%s",spool,getngdir(rcline[ngnum]));
a1st = getngmin(dirname,0L);
if (!a1st) /* nothing there at all? */
a1st = ngsize+1; /* aim them at end of newsgroup */
# ifdef CACHEFIRST
abs1st[ngnum] = a1st;
# endif
return a1st;
#endif MININACT
}
/* scan a directory for minimum article number greater than floor */
ART_NUM
getngmin(dirname,floor)
char *dirname;
ART_NUM floor;
{
register DIR *dirp;
register struct DIRTYPE *dp;
register ART_NUM min = 1000000;
register ART_NUM maybe;
register char *p;
char tmpbuf[128];
dirp = opendir(dirname);
if (!dirp)
return 0;
while ((dp = readdir(dirp)) != Null(struct DIRTYPE *)) {
if ((maybe = atol(dp->d_name)) < min && maybe > floor) {
for (p = dp->d_name; *p; p++)
if (!isdigit(*p))
goto nope;
if (*dirname == '.' && !dirname[1])
stat(dp->d_name, &filestat);
else {
sprintf(tmpbuf,"%s/%s",dirname,dp->d_name);
stat(tmpbuf, &filestat);
}
if (! (filestat.st_mode & S_IFDIR))
min = maybe;
}
nope:
;
}
closedir(dirp);
return min==1000000 ? 0 : min;
}
#endif
!STUFFY!FUNK!
echo Extracting artsrch.c
cat >artsrch.c <<'!STUFFY!FUNK!'
/* $Header: artsrch.c,v 4.3.2.4 89/11/27 01:30:00 sob Locked $
*
* $Log: artsrch.c,v $
* Revision 4.3.2.4 89/11/27 01:30:00 sob
* Altered NNTP code per ideas suggested by Bela Lubkin
* <filbo@gorn.santa-cruz.ca.us>
*
* Revision 4.3.2.3 89/11/26 22:54:37 sob
* Added new patches to make rrn faster.
*
* Revision 4.3.2.2 89/11/26 22:20:57 sob
* Added better NNTP support.
*
* Revision 4.3.2.1 89/11/26 22:13:10 sob
* Added support for NNTP
*
* Revision 4.3 85/05/01 11:35:47 lwall
* Baseline for release with 4.3bsd.
*
*/
#include "EXTERN.h"
#include "common.h"
#include "search.h"
#include "term.h"
#include "util.h"
#include "intrp.h"
#include "bits.h"
#include "kfile.h"
#include "head.h"
#include "final.h"
#include "cheat.h"
#ifdef SERVER
#include "server.h"
#endif
#include "ng.h"
#include "artio.h"
#include "INTERN.h"
#include "artsrch.h"
void
artsrch_init()
{
#ifdef ARTSEARCH
#ifdef ZEROGLOB
init_compex(&sub_compex);
init_compex(&art_compex);
#endif
#endif
}
/* search for an article containing some pattern */
#ifdef ARTSEARCH
int
art_search(patbuf,patbufsiz,get_cmd)
char *patbuf; /* if patbuf != buf, get_cmd must */
int patbufsiz;
int get_cmd; /* be set to FALSE!!! */
{
char *pattern; /* unparsed pattern */
register char cmdchr = *patbuf; /* what kind of search? */
register char *s;
bool backward = cmdchr == '?' || cmdchr == Ctl('p');
/* direction of search */
COMPEX *compex; /* which compiled expression */
char *cmdlst = Nullch; /* list of commands to do */
int normal_return = SRCH_NOTFOUND; /* assume no commands */
bool saltaway = FALSE; /* store in KILL file? */
char howmuch; /* search just the subjects */
bool doread; /* search read articles? */
bool foldcase = TRUE; /* fold upper and lower case? */
int_count = 0;
if (cmdchr == '/' || cmdchr == '?') { /* normal search? */
if (get_cmd && buf == patbuf)
if (!finish_command(FALSE)) /* get rest of command */
return SRCH_ABORT;
compex = &art_compex;
if (patbuf[1]) {
howmuch = 0;
doread = FALSE;
}
else {
howmuch = art_howmuch;
doread = art_doread;
}
s = cpytill(buf,patbuf+1,cmdchr);/* ok to cpy buf+1 to buf */
pattern = buf;
if (*pattern) {
if (*lastpat)
free(lastpat);
lastpat = savestr(pattern);
}
if (*s) { /* modifiers or commands? */
for (s++; *s && index("Kharc",*s); s++) {
if (*s == 'h') /* scan header */
howmuch = 1;
else if (*s == 'a') /* scan article */
howmuch = 2;
else if (*s == 'r') /* scan read articles */
doread = TRUE;
else if (*s == 'K') /* put into KILL file */
saltaway = TRUE;
else if (*s == 'c') /* make search case sensitive */
foldcase = FALSE;
}
}
while (isspace(*s) || *s == ':')
s++;
if (*s) {
if (*s == 'm' || *s == 'M')
doread = TRUE;
if (*s == 'k') /* grandfather clause */
*s = 'j';
cmdlst = savestr(s);
normal_return = SRCH_DONE;
}
art_howmuch = howmuch;
art_doread = doread;
if (srchahead)
srchahead = -1;
}
else {
register char *h;
howmuch = 0; /* just search subjects */
doread = (cmdchr == Ctl('p'));
if (cmdchr == Ctl('n'))
normal_return = SRCH_SUBJDONE;
compex = &sub_compex;
pattern = patbuf+1;
strcpy(pattern,": *");
h = pattern + strlen(pattern);
interp(h,patbufsiz - (h-patbuf),"%s"); /* fetch current subject */
if (cmdchr == 'K') {
saltaway = TRUE;
cmdchr = 'k';
}
if (cmdchr == 'k') {
normal_return = SRCH_DONE;
cmdlst = savestr("j");
mark_as_read(art); /* this article has this subject */
if (!*h) {
#ifdef VERBOSE
IF(verbose)
fputs("\nCannot delete null subject.\n",stdout) FLUSH;
ELSE
#endif
#ifdef TERSE
fputs("\nNull subject.\n",stdout) FLUSH;
#endif
return SRCH_ABORT;
}
#ifdef VERBOSE
else if (verbose)
printf("\nMarking subject \"%s\" as read.\n",h) FLUSH;
#endif
}
else if (!srchahead)
srchahead = -1;
h[24] = '\0'; /* compensate for notesfiles */
while (*h) {
if (index("/\\[.^*$'\"",*h) != Nullch)
*h++ = '.';
else
h++;
}
#ifdef DEBUGGING
if (debug) {
printf("\npattern = %s\n",pattern) FLUSH;
}
#endif
}
if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) {
/* compile regular expression */
printf("\n%s\n",s) FLUSH;
return SRCH_ABORT;
}
#ifdef KILLFILES
if (saltaway) {
char saltbuf[LBUFLEN];
s = saltbuf;
sprintf(s,"/%s/",pattern);
s += strlen(s);
if (doread)
*s++ = 'r';
if (howmuch==1)
*s++ = 'h';
else if (howmuch==2)
*s++ = 'a';
*s++ = ':';
if (!cmdlst)
cmdlst = savestr("j");
safecpy(s,cmdlst,LBUFLEN-(s-saltbuf));
kf_append(saltbuf);
}
#endif
if (cmdlst && index(cmdlst,'='))
normal_return = SRCH_ERROR; /* listing subjects is an error? */
if (get_cmd) {
fputs("\nSearching...\n",stdout) FLUSH;
/* give them something to read */
}
if (backward) {
if (cmdlst && art < lastart)
art++; /* include current article */
if (doread)
check_first(absfirst);
}
else {
if (art > lastart)
art = (doread ? absfirst : firstart) - 1;
else if (cmdlst && art > absfirst)
art--; /* include current article */
check_first(art);
}
if (srchahead > 0) {
if (!backward)
art = srchahead - 1;
srchahead = -1;
}
assert(!cmdlst || *cmdlst);
for (;;) {
if (int_count) {
int_count = 0;
if (cmdlst)
free(cmdlst);
return SRCH_INTR;
}
if (backward ?
(--art < absfirst || (!doread && art < firstart)) :
(++art > lastart)
) { /* out of articles? */
if (cmdlst)
free(cmdlst);
return normal_return;
}
/*NOSTRICT*/
if (doread || !was_read(art)) {
if (wanted(compex,art,howmuch)) {
/* does the shoe fit? */
if (cmdlst) {
if (perform(cmdlst,TRUE)) {
if (cmdlst)
free(cmdlst);
return SRCH_INTR;
}
}
else {
if (cmdlst)
free(cmdlst);
return SRCH_FOUND;
}
}
else if (!cmdlst && ! (art%50)) {
printf("...%ld",(long)art);
fflush(stdout);
}
}
}
}
/* determine if article fits pattern */
/* returns TRUE if it exists and fits pattern, FALSE otherwise */
bool
wanted(compex, artnum, scope)
COMPEX *compex;
ART_NUM artnum;
char scope;
{
if (!scope) {
char subj_buf[266];
strcpy(subj_buf, "Subject: ");
strncpy(subj_buf+9,fetchsubj(artnum,FALSE,FALSE),256);
#ifdef DEBUGGING
if (debug & DEB_SEARCH_AHEAD)
printf("%s\n",subj_buf) FLUSH;
#endif
return execute(compex,subj_buf) != Nullch;
}
#ifdef CACHESUBJ
else
fetchsubj(artnum,FALSE,FALSE);/* might as well get subject handy */
#endif
#ifdef SERVER
if (scope == 1){
if (nntpopen(artnum,HEAD) == Nullfp) /* we only need the header */
return FALSE;
}
else
#endif
if (artopen(artnum) == Nullfp) /* ensure that article is open */
return FALSE; /* if not, return NO MATCH */
scope--;
while (fgets(buf,LBUFLEN,artfp) != Nullch) {
/* for each line of article */
if (!scope && index(buf,':') == Nullch && *buf != ' ' && *buf != '\t')
/* if headers only and out of header */
return FALSE; /* say no go */
if (execute(compex,buf) != Nullch) {
/* does pattern matcher match? */
return TRUE; /* say Eureka */
}
}
return FALSE; /* out of article, so no match */
}
#endif
!STUFFY!FUNK!
echo Extracting term.h
cat >term.h <<'!STUFFY!FUNK!'
/* $Header: term.h,v 4.3.2.2 90/04/06 20:35:34 sob Exp $
*
* $Log: term.h,v $
* Revision 4.3.2.2 90/04/06 20:35:34 sob
* Added fixes for SCO Xenix sent by ronald@robobar.co.uk.
*
* Revision 4.3.2.1 89/11/28 01:54:03 sob
* Added better support for SIGWINCH.
*
* Revision 4.3.1.2 85/05/13 15:52:05 lwall
* Declared devtty on TERMIO system.
*
* Revision 4.3.1.1 85/05/10 11:41:24 lwall
* Branch for patches.
*
* Revision 4.3 85/05/01 11:51:36 lwall
* Baseline for release with 4.3bsd.
*
*/
#ifdef PUSHBACK
EXT char circlebuf[PUSHSIZE];
EXT int nextin INIT(0);
EXT int nextout INIT(0);
#ifdef PENDING
#ifdef FIONREAD
EXT long iocount INIT(0);
#ifndef lint
#define input_pending() (nextin!=nextout || (ioctl(0, FIONREAD, &iocount),(int)iocount))
#else
#define input_pending() bizarre
#endif lint
#else FIONREAD
#ifdef RDCHK
#define input_pending() (rdchk(0) > 0) /* boolean only */
#else /* RDCHK */
int circfill();
EXT int devtty INIT(0);
#ifndef lint
#define input_pending() (nextin!=nextout || circfill())
#else
#define input_pending() bizarre
#endif lint
#endif /* RDCHK */
#endif FIONREAD
#else PENDING
#ifndef lint
#define input_pending() (nextin!=nextout)
#else
#define input_pending() bizarre
#endif lint
#endif PENDING
#else PUSHBACK
#ifdef PENDING
#ifdef FIONREAD /* must have FIONREAD or O_NDELAY for input_pending() */
#define read_tty(addr,size) read(0,addr,size)
#ifndef lint
#define input_pending() (ioctl(0, FIONREAD, &iocount),(int)iocount)
#else
#define input_pending() bizarre
#endif lint
EXT long iocount INIT(0);
#else FIONREAD
#ifdef RDCHK
#define input_pending() (rdchk(0) > 0) /* boolean only */
#else /* RDCHK */
EXT int devtty INIT(0);
EXT bool is_input INIT(FALSE);
EXT char pending_ch INIT(0);
#ifndef lint
#define input_pending() (is_input || (is_input=read(devtty,&pending_ch,1)))
#else
#define input_pending() bizarre
#endif lint
#endif /* RDCHK */
#endif FIONREAD
#else PENDING
#define read_tty(addr,size) read(0,addr,size)
#define input_pending() (FALSE)
#endif PENDING
#endif PUSHBACK
/* stuff wanted by terminal mode diddling routines */
#ifdef TERMIO
EXT struct termio _tty, _oldtty;
#else
EXT struct sgttyb _tty;
EXT int _res_flg INIT(0);
#endif
EXT int _tty_ch INIT(2);
EXT bool bizarre INIT(FALSE); /* do we need to restore terminal? */
/* terminal mode diddling routines */
#ifdef TERMIO
#define crmode() ((bizarre=1),_tty.c_lflag &=~ICANON,_tty.c_cc[VMIN] = 1,ioctl(_tty_ch,TCSETAF,&_tty))
#define nocrmode() ((bizarre=1),_tty.c_lflag |= ICANON,_tty.c_cc[VEOF] = CEOF,stty(_tty_ch,&_tty))
#define echo() ((bizarre=1),_tty.c_lflag |= ECHO, ioctl(_tty_ch, TCSETA, &_tty))
#define noecho() ((bizarre=1),_tty.c_lflag &=~ECHO, ioctl(_tty_ch, TCSETA, &_tty))
#define nl() ((bizarre=1),_tty.c_iflag |= ICRNL,_tty.c_oflag |= ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
#define nonl() ((bizarre=1),_tty.c_iflag &=~ICRNL,_tty.c_oflag &=~ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
#define savetty() (ioctl(_tty_ch, TCGETA, &_oldtty),ioctl(_tty_ch, TCGETA, &_tty))
#define resetty() ((bizarre=0),ioctl(_tty_ch, TCSETAF, &_oldtty))
#define unflush_output()
#else
#define raw() ((bizarre=1),_tty.sg_flags|=RAW, stty(_tty_ch,&_tty))
#define noraw() ((bizarre=1),_tty.sg_flags&=~RAW,stty(_tty_ch,&_tty))
#define crmode() ((bizarre=1),_tty.sg_flags |= CBREAK, stty(_tty_ch,&_tty))
#define nocrmode() ((bizarre=1),_tty.sg_flags &= ~CBREAK,stty(_tty_ch,&_tty))
#define echo() ((bizarre=1),_tty.sg_flags |= ECHO, stty(_tty_ch, &_tty))
#define noecho() ((bizarre=1),_tty.sg_flags &= ~ECHO, stty(_tty_ch, &_tty))
#define nl() ((bizarre=1),_tty.sg_flags |= CRMOD,stty(_tty_ch, &_tty))
#define nonl() ((bizarre=1),_tty.sg_flags &= ~CRMOD, stty(_tty_ch, &_tty))
#define savetty() (gtty(_tty_ch, &_tty), _res_flg = _tty.sg_flags)
#define resetty() ((bizarre=0),_tty.sg_flags = _res_flg, stty(_tty_ch, &_tty))
#ifdef LFLUSHO
#ifndef lint
EXT int lflusho INIT(LFLUSHO);
#else
EXT long lflusho INIT(LFLUSHO);
#endif lint
#define unflush_output() (ioctl(_tty_ch,TIOCLBIC,&lflusho))
#else
#define unflush_output()
#endif LFLUSHO
#endif TERMIO
#ifdef TIOCSTI
#ifdef lint
#define forceme(c) ioctl(_tty_ch,TIOCSTI,Null(long*)) /* ghad! */
#else
#define forceme(c) ioctl(_tty_ch,TIOCSTI,c) /* pass character in " " */
#endif lint
#else
#define forceme(c)
#endif
/* termcap stuff */
/*
* NOTE: if you don't have termlib you'll either have to define these strings
* and the tputs routine, or you'll have to redefine the macros below
*/
#ifdef HAVETERMLIB
EXT char *BC INIT(Nullch); /* backspace character */
EXT char *UP INIT(Nullch); /* move cursor up one line */
EXT char *CR INIT(Nullch); /* get to left margin, somehow */
EXT char *VB INIT(Nullch); /* visible bell */
EXT char *CL INIT(Nullch); /* home and clear screen */
EXT char *CE INIT(Nullch); /* clear to end of line */
#ifdef CLEAREOL
EXT char *CM INIT(Nullch); /* cursor motion -- PWP */
EXT char *HO INIT(Nullch); /* home cursor -- PWP */
EXT char *CD INIT(Nullch); /* clear to end of display -- PWP */
#endif CLEAREOL
EXT char *SO INIT(Nullch); /* begin standout mode */
EXT char *SE INIT(Nullch); /* end standout mode */
EXT int SG INIT(0); /* blanks left by SO and SE */
EXT char *US INIT(Nullch); /* start underline mode */
EXT char *UE INIT(Nullch); /* end underline mode */
EXT char *UC INIT(Nullch); /* underline a character, if that's how it's done */
EXT int UG INIT(0); /* blanks left by US and UE */
EXT bool AM INIT(FALSE); /* does terminal have automatic margins? */
EXT bool XN INIT(FALSE); /* does it eat 1st newline after automatic wrap? */
EXT char PC INIT(0); /* pad character for use by tputs() */
EXT short ospeed INIT(0); /* terminal output speed, for use by tputs() */
EXT int LINES INIT(0), COLS INIT(0); /* size of screen */
EXT int just_a_sec INIT(960); /* 1 sec at current baud rate */
/* (number of nulls) */
/* define a few handy macros */
#define backspace() tputs(BC,0,putchr) FLUSH
#define clear() tputs(CL,LINES,putchr) FLUSH
#define erase_eol() tputs(CE,1,putchr) FLUSH
#ifdef CLEAREOL
#define clear_rest() tputs(CD,LINES,putchr) FLUSH /* PWP */
#define maybe_eol() if(erase_screen&&can_home_clear)tputs(CE,1,putchr) FLUSH
#endif CLEAREOL
#define underline() tputs(US,1,putchr) FLUSH
#define un_underline() tputs(UE,1,putchr) FLUSH
#define underchar() tputs(UC,0,putchr) FLUSH
#define standout() tputs(SO,1,putchr) FLUSH
#define un_standout() tputs(SE,1,putchr) FLUSH
#define up_line() tputs(UP,1,putchr) FLUSH
#define carriage_return() tputs(CR,1,putchr) FLUSH
#define dingaling() tputs(VB,1,putchr) FLUSH
#else
???????? /* up to you */
#endif
EXT int page_line INIT(1); /* line number for paging in print_line (origin 1) */
void term_init();
void term_set();
#ifdef PUSHBACK
void pushchar();
void mac_init();
void mac_line();
void show_macros();
#endif
char putchr(); /* routine for tputs to call */
bool finish_command();
void eat_typeahead();
void settle_down();
#ifndef read_tty
int read_tty();
#endif
void underprint();
#ifdef NOFIREWORKS
void no_sofire();
void no_ulfire();
#endif
void getcmd();
int get_anything();
void in_char();
int print_lines();
void page_init();
void pad();
void printcmd();
void rubout();
void reprint();
#ifdef CLEAREOL
void home_cursor();
#endif CLEAREOL
#ifdef SIGWINCH
int winch_catcher();
#endif /* SIGWINCH */
!STUFFY!FUNK!
echo Extracting Rnmail.SH
cat >Rnmail.SH <<'!STUFFY!FUNK!'
case $CONFIG in
'') . config.sh ;;
esac
echo "Extracting Rnmail (with variable substitutions)"
$spitshell >Rnmail <<!GROK!THIS!
$startsh
# $Header: Rnmail.SH,v 4.3.2.1 89/11/06 00:30:54 sob Locked $
#
# $Log: Rnmail.SH,v $
# Revision 4.3.2.1 89/11/06 00:30:54 sob
# Added RRN support from NNTP 1.5
#
# Revision 4.3.1.4 85/08/01 14:23:05 lwall
# Added MAILRECORD. Temp file is no longer in /tmp. 'e editor' added.
#
# Revision 4.3.1.3 85/05/20 16:25:17 lwall
# Shouldn't ask editor if EDITOR or VISUAL defined.
#
# Revision 4.3.1.2 85/05/17 10:36:19 lwall
# Added "-- " before .signature.
#
# Revision 4.3.1.1 85/05/10 11:30:38 lwall
# Branch for patches.
#
# Revision 4.3 85/05/01 11:34:18 lwall
# Baseline for release with 4.3bsd.
#
#
# syntax: Rnmail -h headerfile [oldart] or
# Rnmail destination-list or just
# Rnmail
export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh \$0; kill \$\$)
# System dependencies
mailer="${mailer-/bin/mail}"
# if you change this to something that does signatures, take out signature code
# your site name
case $portable in
define)
sitename=\`$hostcmd\`
case \$sitename in
*.*)
;;
*)
sitename=\${sitename}.$domain
;;
esac
;;
undef) sitename="$sitename" ;;
esac
# your organization name
orgname="$orgname"
# what pager you use--if you have kernal paging use cat
pager="\${PAGER-$pager}"
# how you derive full names, bsd, usg, or other
nametype="$nametype"
# default editor
defeditor="$defeditor"
# how not to do a newline with echo
n="$n"
c="$c"
test=${test-test}
sed=${sed-sed}
echo=${echo-echo}
cat=${cat-cat}
grep=${grep-grep}
rm=${rm-rm}
!GROK!THIS!
$spitshell >>Rnmail <<'!NO!SUBS!'
dotdir=${DOTDIR-${HOME-$LOGDIR}}
tmpart=$dotdir/.letter
headerfile=""
case $# in
0) ;;
*) case $1 in
-h)
headerfile="$2"
case $# in
3) oldart=$3 ;;
esac
;;
esac
;;
esac
case $headerfile in
'')
case $# in
0)
to=h
while $test "$to" = h ; do
$echo ""
$echo $n "To: $c"
read to
case $to in
h)
$cat <<'EOH'
Type the net address of those people that you wish the message sent to.
Additional recipients may be added on the Cc: line when you edit.
Separate multiple addresses with spaces.
EOH
;;
esac
done
;;
*)
to="$*"
;;
esac
to=`$echo "$to" | $sed 's/ */ /g'`
title=h
while $test "$title" = h ; do
$echo ""
$echo $n "Title/Subject: $c"
read title
case $title in
h)
$cat <<'EOH'
Type the title for your message.
EOH
;;
esac
done
# now build a file with a header for them to edit
orgname=${ORGANIZATION-$orgname}
case $orgname in
/*) orgname=`$cat $orgname` ;;
esac
$cat > $tmpart <<EOHeader
To: $to
Subject: $title
Organization: $orgname
Cc:
Bcc:
EOHeader
;;
*)
$cat < $headerfile > $tmpart
;;
esac
file=h
while $test "$file" = h ; do
$echo ""
$echo $n "Prepared file to include [none]: $c"
read file
case $file in
h)
$cat <<'EOH'
If you have already produced the body of your message, type the filename
for it here. If you just want to proceed directly to the editor, type a
RETURN. In any event, you will be allowed to edit as many times as you
want before you send off the message.
EOH
;;
'')
$echo "" >> $tmpart
state=edit
;;
*)
$cat $file >>$tmpart
state=ask
;;
esac
done
$echo ""
while true ; do
case $state in
edit)
rescue="sleep 1; $cat $tmpart >>${HOME-$LOGDIR}/dead.letter ; $echo Message appended to ${HOME-$LOGDIR}/dead.letter ; exit"
trap "$rescue" 1
trap : 2
case "${VISUAL-${EDITOR-}}" in
'')
tmp=h
;;
*)
tmp=''
;;
esac
while $test "$tmp" = h ; do
$echo $n "Editor [${VISUAL-${EDITOR-$defeditor}}]: $c"
read tmp
case $tmp in
h)
$cat <<'EOH'
Type a return to get the default editor, or type the name of the editor you
prefer. The default editor depends on the VISUAL and EDITOR environment
variables.
EOH
;;
'')
;;
*)
VISUAL=$tmp
export VISUAL
;;
esac
done
${VISUAL-${EDITOR-$defeditor}} $tmpart $oldart
trap "$rescue" 2
state=ask
;;
ask)
$echo ""
$echo $n "Send, abort, edit, or list? $c"
read ans
case $ans in
a*)
state=rescue
;;
e*)
set $ans
case $# in
2) VISUAL="$2" ;;
esac
state=edit
;;
l*)
$pager $tmpart
state=ask
;;
s*)
state=send
;;
h*)
$cat <<'EOH'
Type s to send the message, a to abort and append the message to dead.letter,
e to edit the message again, or l to list the message.
To invoke an alternate editor, type 'e editor'.
EOH
esac
;;
send)
if $test -f $dotdir/.signature; then
echo $n "Append .signature file? [y] $c"
read ans
case $ans in
''|y*)
echo "-- " >> $tmpart
cat $dotdir/.signature >> $tmpart
;;
esac
fi
case $mailer in
*sendmail)
$mailer -t <$tmpart
;;
# but recmail does not know about Bcc, alas
*recmail)
$mailer <$tmpart
;;
*)
set X `$sed <$tmpart -n -e '/^To:/{' -e 's/To: *//p' -e q -e '}'`
shift
set X "$@" `$sed <$tmpart -n -e '/^Cc:/{' -e 's/Cc: *//p' -e q -e '}'`
shift
set X "$@" `$sed <$tmpart -n -e '/^Bcc:/{' -e 's/Bcc: *//p' -e q -e '}'`
shift
$grep -v "^Bcc:" <$tmpart | $mailer "$@"
;;
esac
case $? in
0)
state=cleanup
;;
*)
state=rescue
;;
esac
;;
rescue)
$cat $tmpart >> ${HOME-$LOGDIR}/dead.letter
$echo "Message appended to ${HOME-$LOGDIR}/dead.letter"
$echo "A copy may be temporarily found in $tmpart"
exit
;;
cleanup)
case "${MAILRECORD-none}" in
none)
;;
*) if $cat $tmpart >> $MAILRECORD; then
$echo "Article appended to $MAILRECORD"
else
$echo "Cannot append to $MAILRECORD"
fi
;;
esac
exit
;;
esac
done
!NO!SUBS!
$eunicefix Rnmail
chmod 755 Rnmail
!STUFFY!FUNK!
echo Extracting kfile.c
cat >kfile.c <<'!STUFFY!FUNK!'
/* $Header: kfile.c,v 1.2 90/03/22 23:04:41 sob Exp $
*
* $Log: kfile.c,v $
* Revision 1.2 90/03/22 23:04:41 sob
* Fixes provided by Wayne Davison <drivax!davison>
*
* Revision 4.3.1.3 85/05/29 09:11:52 lwall
* Suppressed some killing messages on -t.
*
* Revision 4.3.1.2 85/05/10 14:21:29 lwall
* Prevented THRU from setting art < absfirst.
*
* Revision 4.3.1.1 85/05/10 11:34:33 lwall
* Branch for patches.
*
* Revision 4.3 85/05/01 11:41:53 lwall
* Baseline for release with 4.3bsd.
*
*/
#include "EXTERN.h"
#include "common.h"
#include "term.h"
#include "util.h"
#include "artsrch.h"
#include "ng.h"
#include "bits.h"
#include "intrp.h"
#include "ngstuff.h"
#include "rcstuff.h"
#include "rn.h"
#include "INTERN.h"
#include "kfile.h"
static bool exitcmds = FALSE;
void
kfile_init()
{
;
}
#ifndef KILLFILES
int
edit_kfile()
{
notincl("^K");
return -1;
}
#else KILLFILES
char killglobal[] = KILLGLOBAL;
char killlocal[] = KILLLOCAL;
void
mention(str)
char *str;
{
#ifdef VERBOSE
IF(verbose) {
#ifdef NOFIREWORKS
no_sofire();
#endif
standout();
fputs(str,stdout);
un_standout();
putchar('\n');
}
ELSE
#endif
#ifdef TERSE
putchar('.');
#endif
fflush(stdout);
}
bool kill_mentioned;
int
do_kfile(kfp,entering)
FILE *kfp;
int entering;
{
art = lastart+1;
fseek(kfp,0L,0); /* rewind file */
while (fgets(buf,LBUFLEN,kfp) != Nullch) {
buf[strlen(buf)-1] = '\0';
if (strnEQ(buf,"THRU",4)) {
ART_NUM tmpart;
tmpart = atol(buf+4)+1;
if (tmpart < absfirst)
tmpart = absfirst;
check_first(tmpart);
firstart = tmpart;
continue;
}
if (*buf == 'X') { /* exit command? */
if (entering) {
exitcmds = TRUE;
continue;
}
strcpy(buf,buf+1);
}
else {
if (!entering)
continue;
}
if (*buf == '&') {
mention(buf);
switcheroo();
}
else if (*buf == '/' && firstart <= lastart) {
mention(buf);
kill_mentioned = TRUE;
switch (art_search(buf, (sizeof buf), FALSE)) {
case SRCH_ABORT:
continue;
case SRCH_INTR:
#ifdef VERBOSE
IF(verbose)
printf("\n(Interrupted at article %ld)\n",(long)art)
FLUSH;
ELSE
#endif
#ifdef TERSE
printf("\n(Intr at %ld)\n",(long)art) FLUSH;
#endif
return -1;
case SRCH_DONE:
break;
case SRCH_SUBJDONE:
fputs("\tsubject not found (???)\n",stdout) FLUSH;
break;
case SRCH_NOTFOUND:
fputs("\tnot found\n",stdout) FLUSH;
break;
case SRCH_FOUND:
fputs("\tfound\n",stdout) FLUSH;
}
}
}
return 0;
}
void
kill_unwanted(starting,message,entering)
ART_NUM starting;
char *message;
int entering;
{
bool intr = FALSE; /* did we get an interrupt? */
ART_NUM oldfirst;
bool anytokill = (toread[ng] > 0);
if (localkfp || globkfp) {
if (!entering && !exitcmds)
return;
exitcmds = FALSE;
oldfirst = firstart;
firstart = starting;
clear();
#ifdef VERBOSE
# ifdef TERSE
if (message && (verbose || entering))
# else
if (message)
# endif
#else
if (message && entering)
#endif
fputs(message,stdout) FLUSH;
kill_mentioned = FALSE;
if (localkfp)
intr = do_kfile(localkfp,entering);
if (globkfp && !intr)
intr = do_kfile(globkfp,entering);
if (entering && localkfp && !intr)
setthru(lastart);
putchar('\n') FLUSH;
if (entering && kill_mentioned)
#ifdef VERBOSE
IF(verbose)
get_anything();
ELSE
#endif
#ifdef TERSE
pad(just_a_sec/3);
#endif
if (anytokill) /* if there was anything to kill */
forcelast = FALSE; /* allow for having killed it all */
firstart = oldfirst;
}
}
void
setthru(thru)
ART_NUM thru;
{
FILE *newkfp;
fseek(localkfp,0L,0); /* rewind current file */
strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
UNLINK(buf); /* to prevent file reuse */
if (newkfp = fopen(buf,"w")) {
fprintf(newkfp,"THRU %ld\n",(long)thru);
while (fgets(buf,LBUFLEN,localkfp) != Nullch) {
if (strnEQ(buf,"THRU",4))
continue;
fputs(buf,newkfp);
}
fclose(newkfp);
open_kfile(KF_LOCAL); /* and reopen local file */
}
else
printf(cantcreate,buf) FLUSH;
}
/* edit KILL file for newsgroup */
int
edit_kfile()
{
int r = -1;
if (in_ng)
strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
else
strcpy(buf,filexp(getval("KILLGLOBAL",killglobal)));
if ((r = makedir(buf,MD_FILE)) >= 0) {
sprintf(cmd_buf,"%s %s",
filexp(getval("VISUAL",getval("EDITOR",defeditor))),buf);
printf("\nEditing %s KILL file:\n%s\n",
(in_ng?"local":"global"),cmd_buf) FLUSH;
resetty(); /* make sure tty is friendly */
r = doshell(sh,cmd_buf);/* invoke the shell */
noecho(); /* and make terminal */
crmode(); /* unfriendly again */
open_kfile(in_ng);
}
else
printf("Can't make %s\n",buf) FLUSH;
return r;
}
void
open_kfile(local)
int local;
{
char *kname = filexp(local ?
getval("KILLLOCAL",killlocal) :
getval("KILLGLOBAL",killglobal)
);
stat(kname,&filestat);
if (!filestat.st_size) /* nothing in the file? */
UNLINK(kname); /* delete the file */
if (local) {
if (localkfp)
fclose(localkfp);
localkfp = fopen(kname,"r");
}
else {
if (globkfp)
fclose(globkfp);
globkfp = fopen(kname,"r");
}
}
void
kf_append(cmd)
char *cmd;
{
strcpy(cmd_buf,filexp(getval("KILLLOCAL",killlocal)));
if (makedir(cmd_buf,MD_FILE) >= 0) {
#ifdef VERBOSE
IF(verbose)
printf("\nDepositing command in %s...",cmd_buf);
ELSE
#endif
#ifdef TERSE
printf("\n--> %s...",cmd_buf);
#endif
fflush(stdout);
sleep(2);
if ((tmpfp = fopen(cmd_buf,"a")) != Nullfp) {
fseek(tmpfp,0L,2); /* get to EOF for sure */
fprintf(tmpfp,"%s\n",cmd);
fclose(tmpfp);
fputs("done\n",stdout) FLUSH;
}
else
printf(cantopen,cmd_buf) FLUSH;
}
}
#endif KILLFILES
!STUFFY!FUNK!
echo Extracting art.h
cat >art.h <<'!STUFFY!FUNK!'
/* $Header: art.h,v 4.3 85/05/01 11:35:29 lwall Exp $
*
* $Log: art.h,v $
* Revision 4.3 85/05/01 11:35:29 lwall
* Baseline for release with 4.3bsd.
*
*/
/* do_article() return values */
#define DA_NORM 0
#define DA_RAISE 1
#define DA_CLEAN 2
#define DA_TOEND 3
void art_init();
int do_article();
int page_switch();
bool innermore();
!STUFFY!FUNK!
echo ""
echo "End of kit 7 (of 9)"
cat /dev/null >kit7isdone
config=true
for iskit in 1 2 3 4 5 6 7 8 9 ; do
if test -f kit${iskit}isdone; then
echo "You have run kit ${iskit}."
else
echo "You still need to run kit ${iskit}."
config=false
fi
done
case $config in
true)
echo "You have run all your kits. Please read README and then type Configure."
chmod 755 Configure
;;
esac
: I do not append .signature, but someone might mail this.
exit