Article 2705 of comp.sources.unix:
Path: nntpd.lkg.dec.com!crl.dec.com!crl.dec.com!bloom-beacon.mit.edu!news.kei.com!news.mathworks.com!newsfeed.internetmci.com!in1.uu.net!news1.digital.com!vixie!vixie!not-for-mail
From: davison@borland.com (Wayne Davison)
Newsgroups: comp.sources.unix
Subject: v29i047: trn-3.6 - threaded newsreader based on RN, V3.6, Part10/14
Date: 29 Oct 1995 01:33:00 -0800
Organization: Vixie Enterprises
Lines: 3626
Sender: vixie@vix.com
Approved: vixie@gw.home.vix.com
Message-ID: <46vhoc$t53@gw.home.vix.com>
References: <1.814959141.29825@gw.home.vix.com>
NNTP-Posting-Host: gw.home.vix.com

Submitted-By: davison@borland.com (Wayne Davison)
Posting-Number: Volume 29, Issue 47
Archive-Name: trn-3.6/part10

#!/bin/sh
# This is `part10' (part 10 of a multipart archive).
# Do not concatenate these parts, unpack them in order with `/bin/sh'.
# File `trn-3.6/term.c' is being continued...
#
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  echo 'WARNING: not restoring timestamps.  Consider getting and'
  echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if test ! -r _sharseq.tmp; then
  echo 'Please unpack part 1 first!'
  exit 1
fi
shar_sequence=`cat _sharseq.tmp`
if test "$shar_sequence" != 10; then
  echo "Please unpack part $shar_sequence next!"
  exit 1
fi
if test ! -f _sharnew.tmp; then
  echo 'x - still skipping trn-3.6/term.c'
else
  echo 'x - continuing file trn-3.6/term.c'
  sed 's/^X//' << 'SHAR_EOF' >> 'trn-3.6/term.c' &&
X    if (!*US && !*UC) {			/* no underline mode? */
X	US = SO;			/* substitute standout mode */
X	UE = SE;
X	UG = SG;
X    }
X    LINES = tgetnum("li");		/* lines per page */
X    COLS = tgetnum("co");		/* columns on page */
X
X#ifdef TIOCGWINSZ
X    { struct winsize ws;
X	if (ioctl(0, TIOCGWINSZ, &ws) >= 0 && ws.ws_row > 0 && ws.ws_col > 0) {
X	    LINES = ws.ws_row;
X	    COLS = ws.ws_col;
X	}
X    }
X#endif
X	
X    AM = tgetflag("am");		/* terminal wraps automatically? */
X    XN = tgetflag("xn");		/* then eats next newline? */
X    VB = Tgetstr("vb");
X    if (!*VB)
X	VB = "\007";
X    CR = Tgetstr("cr");
X    if (!*CR) {
X	if (tgetflag("nc") && *UP) {
X	    CR = safemalloc((MEM_SIZE)strlen(UP)+2);
X	    sprintf(CR,"%s\r",UP);
X	}
X	else
X	    CR = "\r";
X    }
X#ifdef TIOCGWINSZ
X	if (ioctl(1, TIOCGWINSZ, &winsize) >= 0) {
X		if (winsize.ws_row > 0)
X		    LINES = winsize.ws_row;
X		if (winsize.ws_col > 0)
X		    COLS = winsize.ws_col;
X	}
X#endif
X#else
X    ??????				/* Roll your own... */
X#endif
X    termlib_init();
X    line_col_calcs();
X    noecho();				/* turn off echo */
X    crmode();				/* enter cbreak mode */
X
X    mac_init(tcbuf);
X}
X
Xvoid
Xset_macro(seq,def)
Xchar *seq;	/* input sequence of keys */
Xchar *def;	/* definition */
X{
X    mac_line(def,seq,0);
X    /* check for common (?) brain damage: ku/kd/etc sequence may be the
X     * cursor move sequence instead of the input sequence.
X     * (This happens on the local xterm definitions.)
X     * Try to recognize and adjust for this case.
X     */
X    if (seq[0] == '\033' && seq[1] == '[' && seq[2]) {
X	char lbuf[LBUFLEN];	/* copy of possibly non-writable string */
X	strcpy(lbuf,seq);
X	lbuf[1] = 'O';
X	mac_line(def,lbuf,0);
X    }
X    if (seq[0] == '\033' && seq[1] == 'O' && seq[2]) {
X	char lbuf[LBUFLEN];	/* copy of possibly non-writable string */
X	strcpy(lbuf,seq);
X	lbuf[1] = '[';
X	mac_line(def,lbuf,0);
X    }
X}
X
X/* Turn the arrow keys into macros that do some basic trn functions.
X** Code provided by Clifford Adams.
X*/
Xvoid
Xarrow_macros(tmpbuf)
Xchar *tmpbuf;
X{
X    char lbuf[256];			/* should be long enough */
X    char *tmpaddr = tmpbuf;
X    register char *tmpstr;
X
X    /* If arrows are defined as single keys, we probably don't
X     * want to redefine them.  (The tvi912c defines kl as ^H)
X     */
X    strcpy(lbuf,Tgetstr("ku"));		/* up */
X    /* '(' at article or pager, '[' in thread sel, 'p' otherwise */
X    if ((int)strlen(lbuf) > 1)
X	set_macro(lbuf,"%(%m=[ap]?\\(:%(%m=t?[:p))");
X
X    strcpy(lbuf,Tgetstr("kd"));		/* down */
X    /* ')' at article or pager, ']' in thread sel, 'n' otherwise */
X    if ((int)strlen(lbuf) > 1)
X	set_macro(lbuf,"%(%m=[ap]?\\):%(%m=t?]:n))");
X
X    strcpy(lbuf,Tgetstr("kl"));		/* left */
X    /* '[' at article or pager, '<' otherwise */
X    if ((int)strlen(lbuf) > 1)
X	set_macro(lbuf,"%(%m=[ap]?\\[:<)");
X
X    strcpy(lbuf,Tgetstr("kr"));		/* right */
X    /* CR at newsgroups, ']' at article or pager, '>' otherwise */
X    if ((int)strlen(lbuf) > 1)
X	set_macro(lbuf,"%(%m=n?^j:%(%m=[ap]?\\]:>))");
X}
X
Xvoid
Xmac_init(tcbuf)
Xchar *tcbuf;
X{
X    char tmpbuf[1024];
X
X    /* set up the Xterm mouse sequence */
X    sprintf(tmpbuf,"\033[M");	/* enter mouse escape sequence */
X    set_macro(tmpbuf,"\003");
X
X    if (auto_arrow_macros)
X	arrow_macros(tmpbuf);
X    if (use_threads)
X	tmpfp = fopen(filexp(getval("TRNMACRO",TRNMACRO)),"r");
X    else
X	tmpfp = Nullfp;
X    if (!tmpfp)
X	tmpfp = fopen(filexp(getval("RNMACRO",RNMACRO)),"r");
X    if (tmpfp) {
X	while (fgets(tcbuf,1024,tmpfp) != Nullch) {
X	    mac_line(tcbuf,tmpbuf,(sizeof tmpbuf));
X	}
X	fclose(tmpfp);
X    }
X}
X
Xvoid
Xmac_line(line,tmpbuf,tbsize)
Xchar *line;
Xchar *tmpbuf;
Xint tbsize;
X{
X    register char *s, *m;
X    register KEYMAP *curmap;
X    register int ch;
X    register int garbage = 0;
X    static char override[] = "\nkeymap overrides string\n";
X
X    if (topmap == Null(KEYMAP*))
X	topmap = newkeymap();
X    if (*line == '#' || *line == '\n')
X	return;
X    if (line[ch = strlen(line)-1] == '\n')
X	line[ch] = '\0';
X    /* A 0 length signifies we already parsed the macro into tmpbuf,
X    ** so line is just the definition. */
X    if (tbsize)
X	m = dointerp(tmpbuf,tbsize,line," \t");
X    else
X	m = line;
X    if (!*m)
X	return;
X    while (*m == ' ' || *m == '\t') m++;
X    for (s=tmpbuf,curmap=topmap; *s; s++) {
X	ch = *s & 0177;
X	if (s[1] == '+' && isdigit(s[2])) {
X	    s += 2;
X	    garbage = (*s & KM_GMASK) << KM_GSHIFT;
X	}
X	else
X	    garbage = 0;
X	if (s[1]) {
X	    if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) {
X		if (tbsize)
X		    fputs(override,stdout) FLUSH;
X		free(curmap->km_ptr[ch].km_str);
X		curmap->km_ptr[ch].km_str = Nullch;
X	    }
X	    curmap->km_type[ch] = KM_KEYMAP + garbage;
X	    if (curmap->km_ptr[ch].km_km == Null(KEYMAP*))
X		curmap->km_ptr[ch].km_km = newkeymap();
X	    curmap = curmap->km_ptr[ch].km_km;
X	}
X	else {
X	    if (tbsize && (curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP)
X		fputs(override,stdout) FLUSH;
X	    else {
X		curmap->km_type[ch] = KM_STRING + garbage;
X		curmap->km_ptr[ch].km_str = savestr(m);
X	    }
X	}
X    }
X}
X
XKEYMAP*
Xnewkeymap()
X{
X    register int i;
X    register KEYMAP *map;
X
X#ifndef lint
X    map = (KEYMAP*)safemalloc(sizeof(KEYMAP));
X#else
X    map = Null(KEYMAP*);
X#endif /* lint */
X    for (i=127; i>=0; --i) {
X	map->km_ptr[i].km_km = Null(KEYMAP*);
X	map->km_type[i] = KM_NOTHIN;
X    }
X    return map;
X}
X
Xvoid
Xshow_macros()
X{
X    char prebuf[64];
X
X    if (topmap != Null(KEYMAP*)) {
X	print_lines("Macros:\n",STANDOUT);
X	*prebuf = '\0';
X	show_keymap(topmap,prebuf);
X    }
X    else {
X	print_lines("No macros defined.\n", NOMARKING);
X    }
X}
X
Xvoid
Xshow_keymap(curmap,prefix)
Xregister KEYMAP *curmap;
Xchar *prefix;
X{
X    register int i;
X    register char *next = prefix + strlen(prefix);
X    register int kt;
X
X    for (i=0; i<128; i++) {
X	if (kt = curmap->km_type[i]) {
X	    if (i < ' ')
X		sprintf(next,"^%c",i+64);
X	    else if (i == ' ')
X		strcpy(next,"\\040");
X	    else if (i == 127)
X		strcpy(next,"^?");
X	    else
X		sprintf(next,"%c",i);
X	    if ((kt >> KM_GSHIFT) & KM_GMASK) {
X		sprintf(cmd_buf,"+%d", (kt >> KM_GSHIFT) & KM_GMASK);
X		strcat(next,cmd_buf);
X	    }
X	    switch (kt & KM_TMASK) {
X	    case KM_NOTHIN:
X		sprintf(cmd_buf,"%s	%c\n",prefix,i);
X		print_lines(cmd_buf,NOMARKING);
X		break;
X	    case KM_KEYMAP:
X		show_keymap(curmap->km_ptr[(char)i].km_km, prefix);
X		break;
X	    case KM_STRING:
X		sprintf(cmd_buf,"%s	%s\n",prefix,curmap->km_ptr[i].km_str);
X		print_lines(cmd_buf,NOMARKING);
X		break;
X	    case KM_BOGUS:
X		sprintf(cmd_buf,"%s	BOGUS\n",prefix);
X		print_lines(cmd_buf,STANDOUT);
X		break;
X	    }
X	}
X    }
X}
X
X/* routine to pass to tputs */
X
Xchar
Xputchr(ch)
Xregister char_int ch;
X{
X    putchar(ch);
X#ifdef lint
X    ch = Null(char);
X    ch = ch;
X#endif
X    return((char) 0);
X}
X
Xint not_echoing = 0;
X
Xvoid
Xhide_pending()
X{
X    not_echoing = 1;
X    pushchar(0200);
X}
X
Xbool
Xmacro_pending()
X{
X    if (nextout != nextin) {
X	if (circlebuf[nextout] == '\200') {
X	    switch (not_echoing) {
X	    case 0:
X		break;
X	    case 1:
X		nextout++;
X		nextout %= PUSHSIZE;
X		not_echoing = 0;
X		break;
X	    default:
X		circlebuf[nextout] = '\n';
X		not_echoing = 0;
X		break;
X	    }
X	    return nextout != nextin;
X	}
X	return 1;
X    }
X    return 0;
X}
X
X/* input the 2nd and succeeding characters of a multi-character command */
X/* returns TRUE if command finished, FALSE if they rubbed out first character */
X
Xint buflimit = LBUFLEN;
X
Xbool
Xfinish_command(donewline)
Xint donewline;
X{
X    register char *s;
X    register bool quoteone = FALSE;
X
X    s = buf;
X    if (s[1] != FINISHCMD)		/* someone faking up a command? */
X	return TRUE;
X    if (not_echoing)
X	not_echoing = 2;
X    do {
X      top:
X	if (not_echoing)
X	    ;
X	else if (*(unsigned char *)s < ' ') {
X	    putchar('^');
X	    putchar(*s | 64);
X	}
X	else if (*s == '\177') {
X	    putchar('^');
X	    putchar('?');
X	}
X	else
X	    putchar(*s);		/* echo previous character */
X	s++;
X	if (s - buf == buflimit)
X	    break;
Xre_read:
X	fflush(stdout);
X	getcmd(s);
X	if (quoteone) {
X	    quoteone = FALSE;
X	    continue;
X	}
X	if (errno || *s == '\f') {
X	    *s = Ctl('r');		/* force rewrite on CONT */
X	}
X	if (*s == '\033') {		/* substitution desired? */
X#ifdef ESCSUBS
X	    char tmpbuf[4], *cpybuf;
X
X	    tmpbuf[0] = '%';
X	    read_tty(&tmpbuf[1],1);
X#ifdef RAWONLY
X	    tmpbuf[1] &= 0177;
X#endif
X	    tmpbuf[2] = '\0';
X	    if (tmpbuf[1] == 'h') {
X		(void) help_subs();
X		*s = '\0';
X		reprint();
X		goto re_read;
X	    }
X	    else if (tmpbuf[1] == '\033') {
X		*s = '\0';
X		cpybuf = savestr(buf);
X		interp(buf, (sizeof buf), cpybuf);
X		free(cpybuf);
X		s = buf + strlen(buf);
X		reprint();
X		goto re_read;
X	    }
X	    else {
X		interp(s,(sizeof buf) - (s-buf),tmpbuf);
X		fputs(s,stdout);
X		s += strlen(s);
X	    }
X	    goto re_read;
X#else
X	    notincl("^[");
X	    *s = '\0';
X	    reprint();
X	    goto re_read;
X#endif
X	}
X	else if (*s == ERASECH) {	/* they want to rubout a char? */
X	    rubout();
X	    s--;			/* discount the char rubbed out */
X	    if (*(unsigned char *)s < ' ' || *s == '\177')
X		rubout();
X	    if (s == buf) {		/* entire string gone? */
X		fflush(stdout);		/* return to single char command mode */
X		return FALSE;
X	    }
X	    else
X		goto re_read;
X	}
X	else if (*s == KILLCH) {	/* wipe out the whole line? */
X	    while (s-- != buf) {	/* emulate that many ERASEs */
X		rubout();
X		if (*(unsigned char *)s < ' ' || *s == '\177')
X		    rubout();
X	    }
X	    fflush(stdout);
X	    return FALSE;		/* return to single char mode */
X	}
X#ifdef WORDERASE
X	else if (*s == Ctl('w')) {	/* wipe out one word? */
X	    *s-- = ' ';
X	    while (!isspace(*s) || isspace(s[1])) {
X		rubout();
X		if (s-- == buf) {
X		    fflush(stdout);
X		    return FALSE;	/* return to single char mode */
X		}
X		if (*(unsigned char *)s < ' ' || *s == '\177')
X		    rubout();
X	    }
X	    s++;
X	    goto re_read;
X	}
X#endif
X	else if (*s == Ctl('r')) {
X	    *s = '\0';
X	    reprint();
X	    goto re_read;
X	}
X	else if (*s == Ctl('v')) {
X	    putchar('^');
X	    backspace();
X	    fflush(stdout);
X	    getcmd(s);
X	    goto top;
X	}
X	else if (*s == '\\') {
X	    quoteone = TRUE;
X	}
X#if defined(__bsdi__) || defined(cray)
X    } while (*s != '\r' && *s != '\n'); /* until CR or NL (not echoed) */
X#else
X    } while (*s != '\n');		/* until a newline (not echoed) */
X#endif
X    *s = '\0';				/* terminate the string nicely */
X    if (donewline)
X	putchar('\n') FLUSH;
X    return TRUE;			/* say we succeeded */
X}
X
Xbool
Xfinish_dblchar()
X{
X    bool ret;
X    int buflimit_save = buflimit;
X    int not_echoing_save = not_echoing;
X    buflimit = 2;
X    ret = finish_command(FALSE);
X    buflimit = buflimit_save;
X    not_echoing = not_echoing_save;
X    return ret;
X}
X
X/* discard any characters typed ahead */
X
Xvoid
Xeat_typeahead()
X{
X    if (!typeahead && !macro_pending()) { /* cancel only keyboard stuff */
X#ifdef PENDING
X	while (input_pending())
X	    read_tty(buf,sizeof(buf));
X#else /* this is probably v7 */
X# ifdef I_SGTTY
X	ioctl(_tty_ch,TIOCSETP,&_tty);
X# else
X#  ifdef I_TERMIO
X	ioctl(_tty_ch,TCSETAW,&_tty);
X#  else
X	tcsetattr(_tty_ch,TCSAFLUSH,&_tty);
X#  endif
X# endif
X#endif
X    }
X}
X
Xvoid
Xsave_typeahead(buf, len)
Xchar *buf;
Xint len;
X{
X    int cnt;
X
X    while (input_pending()) {
X	cnt = read_tty(buf, len);
X	buf += cnt;
X	len -= cnt;
X    }
X    *buf = '\0';
X}
X
Xvoid
Xsettle_down()
X{
X    dingaling();
X    fflush(stdout);
X    /*sleep(1);*/
X    nextout = nextin;			/* empty circlebuf */
X    eat_typeahead();
X}
X
X/* read a character from the terminal, with multi-character pushback */
X
Xint
Xread_tty(addr,size)
Xchar *addr;
Xint size;
X{
X    if (macro_pending()) {
X	*addr = circlebuf[nextout++];
X	nextout %= PUSHSIZE;
X	return 1;
X    }
X    else {
X	size = read(0,addr,size);
X#ifdef RAWONLY
X	*addr &= 0177;
X#endif
X	return size;
X    }
X}
X
X#ifdef PENDING
X# if !defined (FIONREAD) && !defined (HAS_RDCHK)
Xint
Xcircfill()
X{
X    register int Howmany;
X
X    errno = 0;
X    Howmany = read(devtty,circlebuf+nextin,1);
X
X    if (Howmany < 0 && (errno == EAGAIN || errno == EINTR))
X	Howmany = 0;
X    if (Howmany) {
X	nextin += Howmany;
X	nextin %= PUSHSIZE;
X    }
X    return Howmany;
X}
X# endif /* PENDING */
X#endif /* FIONREAD */
X
Xvoid
Xpushchar(c)
Xchar_int c;
X{
X    nextout--;
X    if (nextout < 0)
X	nextout = PUSHSIZE - 1;
X    if (nextout == nextin) {
X	fputs("\npushback buffer overflow\n",stdout) FLUSH;
X	sig_catcher(0);
X    }
X    circlebuf[nextout] = c;
X}
X
X/* print an underlined string, one way or another */
X
Xvoid
Xunderprint(s)
Xregister char *s;
X{
X    assert(UC);
X    if (*UC) {		/* char by char underline? */
X	while (*s) {
X	    if (*(unsigned char *)s < ' ') {
X		putchar('^');
X		backspace();/* back up over it */
X		underchar();/* and do the underline */
X		putchar(*s+64);
X		backspace();/* back up over it */
X		underchar();/* and do the underline */
X	    }
X	    else {
X		putchar(*s);
X		backspace();/* back up over it */
X		underchar();/* and do the underline */
X	    }
X	    s++;
X	}
X    }
X    else {		/* start and stop underline */
X	underline();	/* start underlining */
X	while (*s) {
X	    if (*(unsigned char *)s < ' ') {
X		putchar('^');
X		putchar(*s+64);
X	    }
X	    else
X		putchar(*s);
X	    s++;
X	}
X	un_underline();	/* stop underlining */
X    }
X}
X
X/* keep screen from flashing strangely on magic cookie terminals */
X
X#ifdef NOFIREWORKS
Xvoid
Xno_sofire()
X{
X    if (*UP && *SE) {		/* should we disable fireworks? */
X	putchar('\n');
X	un_standout();
X	up_line();
X	carriage_return();
X    }
X}
X
Xvoid
Xno_ulfire()
X{
X    if (*UP && *US) {		/* should we disable fireworks? */
X	putchar('\n');
X	un_underline();
X	up_line();
X	carriage_return();
X    }
X}
X#endif
X
X/* get a character into a buffer */
X
Xvoid
Xgetcmd(whatbuf)
Xregister char *whatbuf;
X{
X    register KEYMAP *curmap;
X    register int i;
X    bool no_macros; 
X    int times = 0;			/* loop detector */
X    char scrchar;
X
Xtryagain:
X    curmap = topmap;
X#ifdef OLD_RN_WAY
X    no_macros = (whatbuf != buf && !macro_pending()); 
X#else
X    no_macros = (whatbuf != buf); 
X#endif
X    for (;;) {
X	int_count = 0;
X	errno = 0;
X	if (read_tty(whatbuf,1) < 0){
X	    if (!errno)
X	        errno = EINTR;
X	    if (errno == EINTR)
X		return;
X	    perror(readerr);
X	    sig_catcher(0);
X	}
X	lastchar = *whatbuf;
X	if (*whatbuf & 0200 || no_macros) {
X	    *whatbuf &= 0177;
X	    goto got_canonical;
X	}
X	if (curmap == Null(KEYMAP*))
X	    goto got_canonical;
X	for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){
X	    read_tty(&scrchar,1);
X	}
X	switch (curmap->km_type[*whatbuf] & KM_TMASK) {
X	case KM_NOTHIN:			/* no entry? */
X	    if (curmap == topmap)	/* unmapped canonical */
X		goto got_canonical;
X	    settle_down();
X	    goto tryagain;
X	case KM_KEYMAP:			/* another keymap? */
X	    curmap = curmap->km_ptr[*whatbuf].km_km;
X	    assert(curmap != Null(KEYMAP*));
X	    break;
X	case KM_STRING:			/* a string? */
X	    pushstring(curmap->km_ptr[*whatbuf].km_str,0200);
X	    if (++times > 20) {		/* loop? */
X		fputs("\nmacro loop?\n",stdout);
X		settle_down();
X	    }
X	    no_macros = FALSE;
X	    goto tryagain;
X	}
X    }
X
Xgot_canonical:
X#ifdef I_SGTTY
X    if (*whatbuf == '\r')
X	*whatbuf = '\n';
X#endif
X    if (whatbuf == buf)
X	whatbuf[1] = FINISHCMD;		/* tell finish_command to work */
X}
X
Xvoid
Xpushstring(str,bits)
Xchar *str;
Xchar_int bits;
X{
X    register int i;
X    char tmpbuf[PUSHSIZE];
X    register char *s = tmpbuf;
X
X    assert(str != Nullch);
X    interp(tmpbuf,PUSHSIZE,str);
X    for (i = strlen(s)-1; i >= 0; --i)
X	pushchar(s[i] ^ bits);
X}
X
Xint
Xget_anything()
X{
X    char tmpbuf[2];
X
Xreask_anything:
X    unflush_output();			/* disable any ^O in effect */
X    standout();
X#ifdef VERBOSE
X    IF(verbose)
X	fputs("[Type space to continue] ",stdout);
X    ELSE
X#endif
X#ifdef TERSE
X	fputs("[MORE] ",stdout);
X#endif
X    un_standout();
X    fflush(stdout);
X    eat_typeahead();
X    if (int_count) {
X	return -1;
X    }
X    cache_until_key();
X    getcmd(tmpbuf);
X    if (errno || *tmpbuf == '\f') {
X	putchar('\n') FLUSH;		/* if return from stop signal */
X	goto reask_anything;		/* give them a prompt again */
X    }
X    if (*tmpbuf == 'h') {
X#ifdef VERBOSE
X	IF(verbose)
X	    fputs("\nType q to quit or space to continue.\n",stdout) FLUSH;
X	ELSE
X#endif
X#ifdef TERSE
X	    fputs("\nq to quit, space to continue.\n",stdout) FLUSH;
X#endif
X	goto reask_anything;
X    }
X    else if (*tmpbuf != ' ' && *tmpbuf != '\n') {
X	carriage_return();
X	erase_eol();	/* erase the prompt */
X	carriage_return();
X	return *tmpbuf == 'q' ? -1 : *tmpbuf;
X    }
X    if (*tmpbuf == '\n') {
X	page_line = LINES - 1;
X	carriage_return();
X	erase_eol();
X	carriage_return();
X    }
X    else {
X	page_line = 1;
X	if (erase_screen)		/* -e? */
X	    clear();			/* clear screen */
X	else {
X	    carriage_return();
X	    erase_eol();		/* erase the prompt */
X	    carriage_return();
X	}
X    }
X    return 0;
X}
X
Xint
Xpause_getcmd()
X{
X    unflush_output();			/* disable any ^O in effect */
X    standout();
X#ifdef VERBOSE
X    IF(verbose)
X	fputs("[Type space or a command] ",stdout);
X    ELSE
X#endif
X#ifdef TERSE
X	fputs("[CMD] ",stdout);
X#endif
X    un_standout();
X    fflush(stdout);
X    eat_typeahead();
X    if (int_count)
X	return -1;
X    cache_until_key();
X    getcmd(buf);
X    if (errno || *buf == '\f')
X	return 0;			/* if return from stop signal */
X    else if (*buf != ' ') {
X	carriage_return();
X	erase_eol();	/* erase the prompt */
X	carriage_return();
X	return *buf;
X    }
X    return 0;
X}
X
Xvoid
Xin_char(prompt, newmode, dflt)
Xchar *prompt;
Xchar_int newmode;
Xchar *dflt;
X{
X    char oldmode = mode;
X
Xreask_in_char:
X    unflush_output();			/* disable any ^O in effect */
X    printf("%s [%s] ", prompt, dflt);
X    fflush(stdout);
X    eat_typeahead();
X    mode = newmode;
X    getcmd(buf);
X    if (errno || *buf == '\f') {
X	putchar('\n') FLUSH;		/* if return from stop signal */
X	goto reask_in_char;		/* give them a prompt again */
X    }
X    setdef(buf,dflt);
X    mode = oldmode;
X}
X
Xvoid
Xin_answer(prompt, newmode)
Xchar *prompt;
Xchar_int newmode;
X{
X    char oldmode = mode;
X
Xreask_in_answer:
X    unflush_output();			/* disable any ^O in effect */
X    fputs(prompt,stdout);
X    fflush(stdout);
X    eat_typeahead();
X    mode = newmode;
Xreinp_in_answer:
X    getcmd(buf);
X    if (errno || *buf == '\f') {
X	putchar('\n') FLUSH;		/* if return from stop signal */
X	goto reask_in_answer;		/* give them a prompt again */
X    }
X    if (*buf != ' ' && *buf != '\n') 
X	if (!finish_command(TRUE))
X	    goto reinp_in_answer;
X    mode = oldmode;
X}
X
Xint
Xprint_lines(what_to_print,hilite)
Xchar *what_to_print;
Xint hilite;
X{
X    register char *s;
X    register int i;
X
X    if (page_line < 0)			/* they do not want to see this? */
X	return -1;
X    for (s=what_to_print; *s; ) {
X	if (page_line >= LINES || int_count) {
X	    if (i = -1, int_count || (i = get_anything())) {
X		page_line = -1;		/* disable further print_lines */
X		return i;
X	    }
X	}
X	page_line++;
X	if (hilite == STANDOUT) {
X#ifdef NOFIREWORKS
X	    if (erase_screen)
X		no_sofire();
X#endif
X	    standout();
X	}
X	else if (hilite == UNDERLINE) {
X#ifdef NOFIREWORKS
X	    if (erase_screen)
X		no_ulfire();
X#endif
X	    underline();
X	}
X	for (i=0; i<COLS; i++) {
X	    if (!*s)
X		break;
X	    if (*(unsigned char *)s >= ' ')
X		putchar(*s);
X	    else if (*s == '\t') {
X		putchar(*s);
X		i = ((i+8) & ~7) - 1; 
X	    }
X	    else if (*s == '\n') {
X		i = 32000;
X	    }
X	    else {
X		i++;
X		putchar('^');
X		putchar(*s + 64);
X	    }
X	    s++;
X	}
X	if (i) {
X	    if (hilite == STANDOUT)
X		un_standout();
X	    else if (hilite == UNDERLINE)
X		un_underline();
X	    if (AM && i == COLS)
X		fflush(stdout);
X	    else
X		putchar('\n') FLUSH;
X	}
X    }
X    return 0;
X}
X
Xvoid
Xpage_init()
X{
X    page_line = 1;
X    if (erase_screen)
X	clear();
X    else
X	putchar('\n') FLUSH;
X}
X
Xvoid
Xpad(num)
Xint num;
X{
X    register int i;
X
X    for (i = num; i; --i)
X	putchar(PC);
X    fflush(stdout);
X}
X
X/* echo the command just typed */
X
X#ifdef VERIFY
Xvoid
Xprintcmd()
X{
X    if (verify && buf[1] == FINISHCMD) {
X	if (*(unsigned char *)buf < ' ') {
X	    putchar('^');
X	    putchar(*buf | 64);
X	    backspace();
X	    backspace();
X	}
X	else {
X	    putchar(*buf);
X	    backspace();
X	}
X	fflush(stdout);
X    }
X}
X#endif
X
Xvoid
Xrubout()
X{
X    backspace();			/* do the old backspace, */
X    putchar(' ');			/*   space, */
X    backspace();			/*     backspace trick */
X}
X
Xvoid
Xreprint()
X{
X    register char *s;
X
X    fputs("^R\n",stdout) FLUSH;
X    for (s = buf; *s; s++) {
X	if (*(unsigned char *)s < ' ') {
X	    putchar('^');
X	    putchar(*s | 64);
X	}
X	else
X	    putchar(*s);
X    }
X}
X
Xvoid
Xhome_cursor()
X{
X    char *tgoto();
X
X    if (!*HO) {			/* no home sequence? */
X	if (!*CM) {		/* no cursor motion either? */
X	    fputs("\n\n\n", stdout);
X	    return;		/* forget it. */
X	}
X	tputs(tgoto(CM, 0, 0), 1, putchr);	/* go to home via CM */
X	return;
X    }
X    else {			/* we have home sequence */
X	tputs(HO, 1, putchr);	/* home via HO */
X    }
X}
X
Xvoid
Xgoto_line(from,to)	/* assumes caller is already at beginning of line */
Xint from,to;
X{
X    char *tgoto(), *str;
X    int cmcost;
X
X    if (from == to)
X	return;
X    if (*CM && !muck_up_clear) {
X	str = tgoto(CM,0,to);
X	cmcost = strlen(str);
X    } else {
X	str = Nullch;
X	cmcost = 9999;
X    }
X    if (to > from) {
X      go_down:
X	if (to - from <= cmcost) {
X	    while(from++ < to)
X		putchar('\n');
X	    return;
X	}
X    } else if(*UP) {
X	if ((from - to) * upcost <= cmcost) {
X	    while(from-- > to)
X		tputs(UP,1,putchr);
X	    return;
X	}
X    } else if (cmcost == 9999) {
X	home_cursor();
X	from = 0;
X	goto go_down;
X    }
X    tputs(str,1,putchr);
X}
X
Xvoid
Xline_col_calcs()
X{
X     if (LINES > 0) {			/* is this a crt? */
X	  if (!initlines || !initlines_specified)
X	       /* no -i or unreasonable value for initlines */
X	       if (outspeed >= B9600) 	/* whole page at >= 9600 baud */
X		    initlines = LINES;
X	       else if (outspeed >= B4800)/* 16 lines at 4800 */
X		    initlines = 16;
X	       else			/* otherwise just header */
X		    initlines = 8;
X     }
X     else {				/* not a crt */
X	  LINES = 30000;		/* so don't page */
X	  CL = "\n\n";			/* put a couple of lines between */
X	  if (!initlines || !initlines_specified)
X	       /* make initlines reasonable */
X	       initlines = 8;
X     }
X     if (COLS <= 0)
X	  COLS = 80;
X}
X
X
X#ifdef SIGWINCH
XSignal_t
Xwinch_catcher(dummy)
Xint dummy;
X{
X    /* Reset signal in case of System V dain bramage */
X    sigset(SIGWINCH, winch_catcher);
X
X    /* Come here if window size change signal received */
X#ifdef TIOCGWINSZ
X    {	struct winsize ws;
X	char lines[10], cols[10];
X	if (ioctl(0, TIOCGWINSZ, &ws) >= 0 && ws.ws_row > 0 && ws.ws_col > 0) {
X	    if (LINES != ws.ws_row || COLS != ws.ws_col) {
X		LINES = ws.ws_row;
X		COLS = ws.ws_col;
X		line_col_calcs();
X		sprintf(lines, "%d", LINES);
X		sprintf(cols, "%d", COLS);
X		export("LINES",lines);
X		export("COLUMNS",cols);
X		if (mode == 't' || mode == 'a' || mode == 'p')
X		    forceme("\f");	/* cause a refresh */
X					/* (defined only if TIOCSTI defined) */
X	    }
X	}
X    }
X#else
X    /* Well, if SIGWINCH is defined, but TIOCGWINSZ isn't, there's    */
X    /* almost certainly something wrong.  Figure it out for yourself, */
X    /* because I don't know how to deal with it :-)                   */
X    ERROR!
X#endif
X}
X#endif
X
Xvoid
Xtermlib_init()
X{
X#ifdef USETITE
X    if (TI && *TI) {
X	tputs(TI,1,putchr);
X	fflush(stdout);
X    }
X#endif
X#ifdef USEKSKE
X    if (KS && *KS) {
X	tputs(KS,1,putchr);
X	fflush(stdout);
X    }
X#endif
X}
X
Xvoid
Xtermlib_reset()
X{
X#ifdef USETITE
X    if (TE && *TE) {
X	tputs(TE,1,putchr);
X	fflush(stdout);
X    }
X#endif
X#ifdef USEKSKE
X    if (KE && *KE) {
X	tputs(KE,1,putchr);
X	fflush(stdout);
X    }
X#endif
X}
X
Xvoid
Xxmouse_on()
X{
X    if (use_xterm_mouse && !xmouse_status) {
X	printf("\033[?1001s");   /* save old highlight mouse tracking */
X	printf("\033[?1000h");   /* enable mouse tracking */
X	xmouse_status = TRUE;
X    }
X}
X
Xvoid
Xxmouse_off()
X{
X    if (use_xterm_mouse && xmouse_status) {
X	printf("\033[?10001");   /* disable mouse tracking */
X	printf("\033[?1001r");   /* restore old highlight mouse tracking */
X	xmouse_status = FALSE;
X    }
X}
SHAR_EOF
  echo 'File trn-3.6/term.c is complete' &&
  $shar_touch -am 1120192994 'trn-3.6/term.c' &&
  chmod 0644 'trn-3.6/term.c' ||
  echo 'restore of trn-3.6/term.c failed'
  shar_count="`wc -c < 'trn-3.6/term.c'`"
  test 30477 -eq "$shar_count" ||
    echo "trn-3.6/term.c: original size 30477, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/term.h ==============
if test -f 'trn-3.6/term.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/term.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/term.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/term.h' &&
X/* $Id: term.h,v 3.0 1992/02/01 03:09:32 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
XEXT char circlebuf[PUSHSIZE];
XEXT int nextin INIT(0);
XEXT int nextout INIT(0);
XEXT char lastchar;
X#ifdef PENDING
X# ifdef FIONREAD
XEXT long iocount INIT(0);
X#  ifndef lint
X#define input_pending() (macro_pending() || (ioctl(0, FIONREAD, &iocount),(int)iocount))
X#  else
X#define input_pending() bizarre
X#  endif /* lint */
X# else /* FIONREAD */
X#  ifdef HAS_RDCHK
X#define input_pending() (macro_pending() || rdchk(0))
X#  else /*  HAS_RDCHK */
Xint circfill();
XEXT int devtty INIT(0);
X#   ifndef lint
X#define input_pending() (macro_pending() || circfill())
X#   else
X#define input_pending() bizarre
X#   endif /* lint */
X#  endif /* HAS_RDCHK */
X# endif /* FIONREAD */
X#else /* PENDING */
X# ifndef lint
X#define input_pending() macro_pending()
X# else
X#define input_pending() bizarre
X# endif /* lint */
X#endif /* PENDING */
X
X/* stuff wanted by terminal mode diddling routines */
X
X#ifdef I_TERMIO
XEXT struct termio _tty, _oldtty;
X#else
X# ifdef I_TERMIOS
XEXT struct termios _tty, _oldtty;
X# else
XEXT struct sgttyb _tty;
XEXT int _res_flg INIT(0);
X# endif
X#endif
X
XEXT int _tty_ch INIT(2);
XEXT bool bizarre INIT(FALSE);			/* do we need to restore terminal? */
X
X/* terminal mode diddling routines */
X
X#ifdef I_TERMIO
X
X#define crmode() ((bizarre=1),_tty.c_lflag &=~ICANON,_tty.c_cc[VMIN] = 1,ioctl(_tty_ch,TCSETAF,&_tty))
X#define nocrmode() ((bizarre=1),_tty.c_lflag |= ICANON,_tty.c_cc[VEOF] = CEOF,stty(_tty_ch,&_tty))
X#define echo()	 ((bizarre=1),_tty.c_lflag |= ECHO, ioctl(_tty_ch, TCSETA, &_tty))
X#define noecho() ((bizarre=1),_tty.c_lflag &=~ECHO, ioctl(_tty_ch, TCSETA, &_tty))
X#define nl()	 ((bizarre=1),_tty.c_iflag |= ICRNL,_tty.c_oflag |= ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
X#define nonl()	 ((bizarre=1),_tty.c_iflag &=~ICRNL,_tty.c_oflag &=~ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
X#define	savetty() (ioctl(_tty_ch, TCGETA, &_oldtty),ioctl(_tty_ch, TCGETA, &_tty))
X#define	resetty() ((bizarre=0),ioctl(_tty_ch, TCSETAF, &_oldtty))
X#define unflush_output()
X
X#else /* !I_TERMIO */
X# ifdef I_TERMIOS
X
X#define crmode() ((bizarre=1), _tty.c_lflag &= ~ICANON,_tty.c_cc[VMIN]=1,tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
X#define nocrmode() ((bizarre=1),_tty.c_lflag |= ICANON,_tty.c_cc[VEOF] = CEOF,tcsetattr(_tty_ch, TCSAFLUSH,&_tty))
X#define echo()	 ((bizarre=1),_tty.c_lflag |= ECHO, tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
X#define noecho() ((bizarre=1),_tty.c_lflag &=~ECHO, tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
X#define nl()	 ((bizarre=1),_tty.c_iflag |= ICRNL,_tty.c_oflag |= ONLCR,tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
X#define nonl()	 ((bizarre=1),_tty.c_iflag &=~ICRNL,_tty.c_oflag &=~ONLCR,tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
X#define	savetty() (tcgetattr(_tty_ch, &_oldtty),tcgetattr(_tty_ch, &_tty))
X#define	resetty() ((bizarre=0),tcsetattr(_tty_ch, TCSAFLUSH, &_oldtty))
X#define unflush_output()
X
X# else /* !I_TERMIOS */
X
X#define raw()	 ((bizarre=1),_tty.sg_flags|=RAW, stty(_tty_ch,&_tty))
X#define noraw()	 ((bizarre=1),_tty.sg_flags&=~RAW,stty(_tty_ch,&_tty))
X#define crmode() ((bizarre=1),_tty.sg_flags |= CBREAK, stty(_tty_ch,&_tty))
X#define nocrmode() ((bizarre=1),_tty.sg_flags &= ~CBREAK,stty(_tty_ch,&_tty))
X#define echo()	 ((bizarre=1),_tty.sg_flags |= ECHO, stty(_tty_ch, &_tty))
X#define noecho() ((bizarre=1),_tty.sg_flags &= ~ECHO, stty(_tty_ch, &_tty))
X#define nl()	 ((bizarre=1),_tty.sg_flags |= CRMOD,stty(_tty_ch, &_tty))
X#define nonl()	 ((bizarre=1),_tty.sg_flags &= ~CRMOD, stty(_tty_ch, &_tty))
X#define	savetty() (gtty(_tty_ch, &_tty), _res_flg = _tty.sg_flags)
X#define	resetty() ((bizarre=0),_tty.sg_flags = _res_flg, stty(_tty_ch, &_tty))
X#  ifdef LFLUSHO
X#   ifndef lint
XEXT int lflusho INIT(LFLUSHO);
X#   else
XEXT long lflusho INIT(LFLUSHO);
X#   endif /* lint */
X#define unflush_output() (ioctl(_tty_ch,TIOCLBIC,&lflusho))
X#  else
X#define unflush_output()
X#  endif /* LFLUSHO */
X# endif /* I_TERMIOS */
X
X#endif /* I_TERMIO */
X
X#ifdef TIOCSTI
X#ifdef lint
X#define forceme(c) ioctl(_tty_ch,TIOCSTI,Null(long*))	/* ghad! */
X#else
X#define forceme(c) ioctl(_tty_ch,TIOCSTI,c) /* pass character in " " */
X#endif /* lint */
X#else
X#define forceme(c)
X#endif
X
X/* termcap stuff */
X
X/*
X * NOTE: if you don't have termlib you'll either have to define these strings
X *    and the tputs routine, or you'll have to redefine the macros below
X */
X
X#ifdef HAS_TERMLIB
XEXT int GT;				/* hardware tabs */
XEXT char *BC INIT(Nullch);		/* backspace character */
XEXT char *UP INIT(Nullch);		/* move cursor up one line */
XEXT char *CR INIT(Nullch);		/* get to left margin, somehow */
XEXT char *VB INIT(Nullch);		/* visible bell */
XEXT char *CL INIT(Nullch);		/* home and clear screen */
XEXT char *CE INIT(Nullch);		/* clear to end of line */
XEXT char *TI INIT(Nullch);		/* initialize terminal */
XEXT char *TE INIT(Nullch);		/* reset terminal */
XEXT char *KS INIT(Nullch);		/* enter `keypad transmit' mode */
XEXT char *KE INIT(Nullch);		/* exit `keypad transmit' mode */
XEXT char *CM INIT(Nullch);		/* cursor motion */
XEXT char *HO INIT(Nullch);		/* home cursor */
XEXT char *IL INIT(Nullch);		/* insert line */
X#ifdef CLEAREOL
XEXT char *CD INIT(Nullch);		/* clear to end of display */
X#endif /* CLEAREOL */
XEXT char *SO INIT(Nullch);		/* begin standout mode */
XEXT char *SE INIT(Nullch);		/* end standout mode */
XEXT int SG INIT(0);			/* blanks left by SO and SE */
XEXT char *US INIT(Nullch);		/* start underline mode */
XEXT char *UE INIT(Nullch);		/* end underline mode */
XEXT char *UC INIT(Nullch);		/* underline a character,
X						 if that's how it's done */
XEXT int UG INIT(0);			/* blanks left by US and UE */
XEXT bool AM INIT(FALSE);		/* does terminal have automatic
X								 margins? */
XEXT bool XN INIT(FALSE);		/* does it eat 1st newline after
X							 automatic wrap? */
XEXT char PC INIT(0);			/* pad character for use by tputs() */
X
X#ifdef _POSIX_SOURCE
XEXT speed_t outspeed INIT(0);		/* terminal output speed, */
X#else
XEXT long outspeed INIT(0);		/* 	for use by tputs() */
X#endif
X
XEXT int LINES INIT(0), COLS INIT(0);	/* size of screen */
XEXT int just_a_sec INIT(960);		/* 1 sec at current baud rate */
X					/* (number of nulls) */
X
X/* define a few handy macros */
X
X#define backspace() tputs(BC,0,putchr) FLUSH
X#define clear() tputs(CL,LINES,putchr) FLUSH
X#define erase_eol() tputs(CE,1,putchr) FLUSH
X#ifdef CLEAREOL
X#define clear_rest() tputs(CD,LINES,putchr) FLUSH
X#define maybe_eol() if(erase_screen&&can_home_clear)tputs(CE,1,putchr) FLUSH
X#endif /* CLEAREOL */
X#define underline() tputs(US,1,putchr) FLUSH
X#define un_underline() tputs(UE,1,putchr) FLUSH
X#define underchar() tputs(UC,0,putchr) FLUSH
X#define standout() tputs(SO,1,putchr) FLUSH
X#define un_standout() tputs(SE,1,putchr) FLUSH
X#define up_line() tputs(UP,1,putchr) FLUSH
X#define insert_line() tputs(IL,1,putchr) FLUSH
X#define carriage_return() tputs(CR,1,putchr) FLUSH
X#define dingaling() tputs(VB,1,putchr) FLUSH
X#else
X  ????????		/* up to you */
X#endif
X
XEXT int page_line INIT(1);	/* line number for paging in
X				 print_line (origin 1) */
X
XEXT bool use_xterm_mouse INIT(FALSE);
XEXT bool xmouse_status INIT(FALSE);	/* TRUE: mouse is on */
X
Xvoid	term_init _((void));
Xvoid	term_set _((char*));
Xvoid	pushchar _((char_int));
Xvoid	pushstring _((char*,char_int));
Xvoid	mac_init _((char*));
Xvoid	mac_line _((char*,char*,int));
Xvoid	show_macros _((void));
Xchar	putchr _((char_int));	/* routine for tputs to call */
Xvoid	hide_pending _((void));
Xbool	macro_pending _((void));
Xbool	finish_command _((int));
Xbool	finish_dblchar _((void));
Xvoid	eat_typeahead _((void));
Xvoid	save_typeahead _((char*, int));
Xvoid	settle_down _((void));
X#ifdef HAS_TERMLIB
Xvoid	termlib_init _((void));
Xvoid	termlib_reset _((void));
X#endif
Xint	read_tty _((char*,int));
Xvoid	underprint _((char*));
X#ifdef NOFIREWORKS
Xvoid	no_sofire _((void));
Xvoid	no_ulfire _((void));
X#endif
Xvoid	getcmd _((char*));
Xint	get_anything _((void));
Xint	pause_getcmd _((void));
Xvoid	in_char _((char*,char_int,char*));
Xvoid	in_answer _((char*,char_int));
Xint	print_lines _((char*,int));
Xvoid	page_init _((void));
Xvoid	pad _((int));
Xvoid	printcmd _((void));
Xvoid	rubout _((void));
Xvoid	reprint _((void));
Xvoid	home_cursor _((void));
Xvoid	goto_line _((int,int));
X#ifdef SIGWINCH
XSignal_t winch_catcher _((int));
X#endif /* SIGWINCH */
Xvoid	arrow_macros _((char*));
Xvoid	xmouse_on _((void));
Xvoid	xmouse_off _((void));
SHAR_EOF
  $shar_touch -am 1110023094 'trn-3.6/term.h' &&
  chmod 0644 'trn-3.6/term.h' ||
  echo 'restore of trn-3.6/term.h failed'
  shar_count="`wc -c < 'trn-3.6/term.h'`"
  test 8877 -eq "$shar_count" ||
    echo "trn-3.6/term.h: original size 8877, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/trn.c ==============
if test -f 'trn-3.6/trn.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/trn.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/trn.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/trn.c' &&
X/*  trn -- threaded readnews program based on rn 4.4
X *
X *  Author/Maintainer of trn: davison@borland.com (Wayne Davison)
X *  Organization: Borland International
X *  Author/Maintainer of rn: sob@bcm.tmc.edu (Stan Barber)
X *  Organization: Baylor College of Medicine, Houston,Tx
X *  Original Author: lwall@sdcrdcf.UUCP (Larry Wall)
X *  Organization: System Development Corporation, Santa Monica
X *
X *  History:
X *	01/14/83 - rn begun
X *	04/08/83 - rn 1.0
X *	09/01/83 - rn 2.0
X *	05/01/85 - rn 4.3
X *	11/01/89 - rn/rrn integration
X *	11/25/89 - trn begun
X *	07/21/90 - trn 1.0
X *	07/04/91 - rn 4.4
X *	11/25/91 - trn 2.0
X *	03/01/93 - trn 3.0 (or so... :-) )
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "patchlevel.h"
Xstatic char rnid[] = "@(#)$Id: trn.c,v 3.0 1991/11/22 00:14:59 davison Trn $";
Xstatic char patchlevel[] = PATCHLEVEL;
X
X#include "INTERN.h"
X#include "common.h"
X#include "trn.h"
X#include "EXTERN.h"
X#include "rcstuff.h"
X#include "term.h"
X#include "final.h"
X#include "search.h"
X#include "ngdata.h"
X#include "ngstuff.h"
X#include "util.h"
X#include "util2.h"
X#include "only.h"
X#include "ngsrch.h"
X#include "help.h"
X#include "last.h"
X#include "init.h"
X#include "intrp.h"
X#include "rcln.h"
X#include "sw.h"
X#include "cache.h"
X#include "addng.h"
X#include "ng.h"
X#include "kfile.h"
X#include "nntp.h"
X
Xvoid
Xrn_init()
X{
X    ;
X}
X
Xvoid
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X    bool foundany;
X    register char *s;
X    bool oh_for_the_good_old_days = FALSE;
X    int direction = 1;
X
X#if !THREAD_INIT
X    /* Default to threaded operation if our name starts with a 't' */
X    if ((s = rindex(argv[0],'/')) == Nullch)
X	s = argv[0];
X    else
X	s++;
X    if (*s == 't')
X	use_threads = TRUE;
X    else
X	select_on = 0;
X#endif
X    foundany = initialize(argc,argv);
X
X    if (maxngtodo)
X	starthere = 0;
X    else if (!foundany) {		/* nothing to do? */
X#ifdef VERBOSE
X	if (verbose)
X	    fputs("\
XNo unread news in subscribed-to newsgroups.  To subscribe to a new\n\
Xnewsgroup use the g<newsgroup> command.\n\
X",stdout) FLUSH;
X#endif
X	starthere = nextrcline;
X    }
X
X    /* loop through all unread news */
X
X    {
X	bool special = FALSE;		/* temporarily allow newsgroup */
X					/*   with no unread news? */
X	bool retry;			/* cycle back to top of list? */
X	NG_NUM recent_ng = 0;
X	
X	current_ng = 0;
X	for (;;) {
X	    retry = FALSE;
X	    if (findlast) {
X		findlast = FALSE;
X		starthere = 0;
X		if (*lastngname) {
X		    if ((ng = find_ng(lastngname)) == nextrcline)
X			ng = 0;
X		    else {
X			set_ngname(lastngname);
X		    	set_toread(ng);
X			if (toread[ng] <= TR_NONE)
X			    ng = 0;
X		    }
X		}
X	    } else {
X		ng = starthere;
X		starthere = 0;
X	    }
X	    while (ng <= nextrcline) {	/* for each newsgroup */
X		if (ng == nextrcline) {	/* after the last newsgroup? */
X		    mode = 'f';
X#ifdef ONLY
X		    if (maxngtodo) {
X			if (retry)
X#ifdef VERBOSE
X			    IF(verbose)
X				printf("\nRestriction %s%s still in effect.\n",
X				    ngtodo[0],
X				    maxngtodo > 1 ? ", etc." : nullstr) FLUSH;
X			    ELSE
X#endif
X#ifdef TERSE
X				fputs("\n(\"Only\" mode.)\n",stdout) FLUSH;
X#endif
X			else {
X#ifdef VERBOSE
X			    IF(verbose)
X				fputs("\nNo articles under restriction.",
X				  stdout) FLUSH;
X			    ELSE
X#endif
X#ifdef TERSE
X				fputs("\nNo \"only\" articles.",stdout) FLUSH;
X#endif
X			    end_only();	/* release the restriction */
X			    retry = TRUE;
X			}
X		    }
X#endif
X		} else {
X		    bool shoe_fits;	/* newsgroup matches restriction? */
X
X		    mode = 'n';
X		    if (toread[ng] >= TR_NONE) {	/* recalc toread? */
X			set_ngname(rcline[ng]);
X			shoe_fits = inlist(ngname);
X			if (shoe_fits)
X			    set_toread(ng);
X			if (paranoid) {
X			    recent_ng = current_ng;
X			    current_ng = ng;
X			    cleanup_rc();
X					/* this may move newsgroups around */
X			    ng = current_ng;
X			    set_ngname(rcline[ng]);
X			}
X		    } else
X			shoe_fits = TRUE;
X		    if (toread[ng] < (emptyOnly || special ? TR_NONE : TR_ONE)
X		     || !shoe_fits) {		/* unwanted newsgroup? */
X			ng += direction;	/* then skip it */
X			if (ng < 0) {
X			   ng = 1;
X			   direction = 1;
X			}
X			continue;
X		    }
X		}
X		special = FALSE;	/* go back to normal mode */
X		if (ng != current_ng) {
X		    recent_ng = current_ng;
X					/* remember previous newsgroup */
X		    current_ng = ng;	/* remember current newsgroup */
X		}
X    reask_newsgroup:
X		unflush_output();	/* disable any ^O in effect */
X		if (ng >= nextrcline) {
X		    dfltcmd = (retry ? "npq" : "qnp");
X#ifdef VERBOSE
X		    IF(verbose)
X			printf("\n****** End of newsgroups -- what next? [%s] ",
X			    dfltcmd);
X		    ELSE
X#endif
X#ifdef TERSE
X			printf("\n**** End -- next? [%s] ", dfltcmd);
X#endif
X		} else {
X		    ThreadedGroup = (use_threads && rcchar[ng] != '0');
X		    dfltcmd = (select_on
X			&& (ART_NUM)toread[ng] >= select_on ? "+ynq" : "ynq");
X#ifdef VERBOSE
X		    IF(verbose)
X			printf("\n%s %3ld unread article%s in %s -- read now? [%s] ",
X			    ThreadedGroup? "======" : "******",
X			    (long)toread[ng], (toread[ng]==TR_ONE ? nullstr : "s"),
X			    ngname, dfltcmd);
X		    ELSE
X#endif
X#ifdef TERSE
X			printf("\n%s %3ld in %s -- read? [%s] ",
X			    ThreadedGroup? "====" : "****",
X			    (long)toread[ng],ngname,dfltcmd);
X#endif
X		}
X		fflush(stdout);
X    reinp_newsgroup:
X		eat_typeahead();
X		getcmd(buf);
X		if (errno || *buf == '\f') {
X		    putchar('\n') FLUSH; /* if return from stop signal */
X		    goto reask_newsgroup;	/* give them a prompt again */
X		}
X		setdef(buf,dfltcmd);
X#ifdef VERIFY
X		printcmd();
X#endif
X    do_command:
X		direction = 1;		/* default to forward motion */
X		addnewbydefault = 0;
X		switch (*buf) {
X		case 'P':		/* goto previous newsgroup */
X		    special = TRUE;	/* don't skip it if toread==0 */
X		    /* FALL THROUGH */
X		case 'p':		/* find previous unread newsgroup */
X		    if (ng > 0)
X			ng--;
X		    direction = -1;	/* go backward in the newsrc */
X		    break;
X		case '-':
X		    ng = recent_ng;	/* recall previous newsgroup */
X		    if (ng < nextrcline)
X			if (!get_ng(rcline[ng],0))
X			    ng = current_ng;
X		    special = TRUE;	/* don't skip it if toread==0 */
X		    break;
X		case 'x':
X		    putchar('\n');
X		    in_char("Confirm: exit and abandon .newsrc changes?",
X			    'A', "yn");
X		    putchar('\n') FLUSH;
X		    if (*buf != 'y')
X			break;
X		    oh_for_the_good_old_days = TRUE;
X		    printf("\nMoving changed version to '.newnewsrc'.");
X		    /* FALL THROUGH */
X		case 'q': case 'Q':	/* quit? */
X		    putchar('\n') FLUSH;
X		    ng = nextrcline+1;	/* satisfy */
X		    retry = FALSE;	/*   loop conditions */
X		    break;
X		case '^':
X		    putchar('\n') FLUSH;
X		    ng = 0;
X		    break;
X		case 'n':		/* find next unread newsgroup */
X		    if (ng == nextrcline) {
X			putchar('\n') FLUSH;
X			retry = TRUE;
X		    } else if (toread[ng] > TR_NONE)
X			retry = TRUE;
X		    ng++;
X		    break;
X		case 'N':		/* goto next newsgroup */
X		    special = TRUE;	/* and don't skip it if toread==0 */
X		    ng++;
X		    break;
X		case '1':		/* goto 1st newsgroup */
X		    ng = 0;
X		    special = TRUE;	/* and don't skip it if toread==0 */
X		    break;
X		case '$':
X		    ng = nextrcline;	/* goto last newsgroup */
X		    retry = TRUE;
X		    break;
X		case 'L':
X		    list_newsgroups();
X		    goto reask_newsgroup;
X		case '/': case '?':	/* scan for newsgroup pattern */
X#ifdef NGSEARCH
X		    switch (ng_search(buf,TRUE)) {
X		    case NGS_ERROR:
X			goto reask_newsgroup;
X		    case NGS_ABORT:
X			goto reinp_newsgroup;
X		    case NGS_INTR:
X#ifdef VERBOSE
X			IF(verbose)
X			    fputs("\n(Interrupted)\n",stdout) FLUSH;
X			ELSE
X#endif
X#ifdef TERSE
X			    fputs("\n(Intr)\n",stdout) FLUSH;
X#endif
X			ng = current_ng;
X			goto reask_newsgroup;
X		    case NGS_FOUND:
X			special = TRUE;	/* don't skip it if toread==0 */
X			break;
X		    case NGS_NOTFOUND:
X#ifdef VERBOSE
X			IF(verbose)
X			    fputs("\n\nNot found -- use a or g to add newsgroups\n",
X				stdout) FLUSH;
X			ELSE
X#endif
X#ifdef TERSE
X			    fputs("\n\nNot found\n",stdout) FLUSH;
X#endif
X			goto reask_newsgroup;
X		    }
X#else
X		    notincl("/");
X#endif
X		    break;
X		case 'm':
X#ifndef RELOCATE
X		    notincl("m");
X		    break;
X#endif		    
X		case 'g':	/* goto named newsgroup */
X		    if (!finish_command(FALSE))
X					/* if they didn't finish command */
X			goto reinp_newsgroup;	/* go try something else */
X		    for (s = buf+1; *s == ' '; s++);
X					/* skip leading spaces */
X#ifdef RELOCATE
X		    if (!*s && *buf == 'm' && ngname && ng < nextrcline)
X			strcpy(s,ngname);
X#endif
X		    {
X		        char *_s;
X			for (_s=s; isdigit(*_s); _s++)
X			    ;
X			if (isspace(*_s))
X			    *_s = '\0';
X		        if (*_s)
X			    /* found non-digit before hitting end */
X			    set_ngname(s);
X			else {
X			    int rcnum;
X			    rcnum = atoi(s);
X			    if (rcnum < nextrcline)
X				set_ngname(rcline[rcnum]);
X			    else {
X				printf("\nOnly %d groups. Try again.\n",
X					nextrcline) FLUSH;
X				goto reask_newsgroup;
X			    }
X			}
X		    }
X		    /* try to find newsgroup */
X#ifdef RELOCATE
X		    if (!get_ng(ngname,(*buf=='m'?GNG_RELOC:0) | GNG_FUZZY))
X#else
X		    if (!get_ng(ngname,GNG_FUZZY))
X#endif
X			ng = current_ng;/* if not found, go nowhere */
X		    special = TRUE;	/* don't skip it if toread==0 */
X		    break;
X#ifdef DEBUG
X		case 'D':
X		    printf("\nTries: %d Hits: %d\n",
X			softtries,softtries-softmisses) FLUSH;
X		    goto reask_newsgroup;
X#endif
X		case '!':		/* shell escape */
X		    if (escapade())	 /* do command */
X			goto reinp_newsgroup;
X					/* if rubbed out, re input */
X		    goto reask_newsgroup;
X		case Ctl('k'):		/* edit global KILL file */
X		    edit_kfile();
X		    goto reask_newsgroup;
X		case 'c':		/* catch up */
X#ifdef CATCHUP
X		    if (ng < nextrcline)
X			ask_catchup();
X		    if (toread[ng] == TR_NONE)
X			ng++;
X#else
X		    notincl("c");
X#endif
X		    break;
X		case 't':
X		    if (!use_threads)
X			printf("\n\nNot running in thread mode.\n");
X		    else if (ng < nextrcline && toread[ng] >= TR_NONE) {
X			bool read_unthreaded = (rcchar[ng] == ':');
X			rcchar[ng] = (read_unthreaded ? '0' : ':');
X			printf("\n\n%s will be read %sthreaded.\n",
X			    rcline[ng], read_unthreaded? "un" : "") FLUSH;
X			set_toread(ng);
X		    }
X		    special = TRUE;	/* don't skip it if toread==0 */
X		    break;
X		case 'u':		/* unsubscribe */
X		    if (ng < nextrcline && toread[ng] >= TR_NONE) {
X					/* unsubscribable? */
X			printf(unsubto,rcline[ng]) FLUSH;
X			rcchar[ng] = NEGCHAR;
X					/* unsubscribe to (from?) it */
X			toread[ng] = TR_UNSUB;
X					/* and make line invisible */
X			ng++;		/* do an automatic 'n' */
X		    }
X		    break;
X		case 'h': {		/* help */
X		    int cmd;
X
X		    if ((cmd = help_ng()) > 0)
X			pushchar(cmd);
X		    goto reask_newsgroup;
X		}
X		case 'A':
X		    if (ng >= nextrcline)
X			break;
Xreask_abandon:
X#ifdef VERBOSE
X		    IF(verbose)
X			in_char("\nAbandon changes to current newsgroup?",
X				'B', "yn");
X		    ELSE
X#endif
X#ifdef TERSE
X			in_char("\nAbandon?", 'B', "ynh");
X#endif
X#ifdef VERIFY
X		    printcmd();
X#endif
X		    putchar('\n') FLUSH;
X		    if (*buf == 'h') {
X#ifdef VERBOSE
X			printf("Type y or SP to abandon the changes to this group since you started trn.\n");
X			printf("Type n to leave the group as it is.\n");
X#else
X			printf("y or SP to abandon changes to this group.\n");
X			printf("n to forget it.\n");
X#endif
X			goto reask_abandon;
X		    } else if (*buf != 'y' && *buf != 'n' && *buf != 'q') {
X			printf(hforhelp);
X			settle_down();
X			goto reask_abandon;
X		    } else if (*buf == 'y')
X			abandon_ng(ng);
X		    special = TRUE;	/* don't skip it if toread==0 */
X		    break;
X		case 'a':
X#ifndef FINDNEWNG
X		    notincl("a");
X		    goto reask_newsgroup;
X#else
X		    /* FALL THROUGH */
X#endif
X		case 'o':
X		case 'O':
X#ifdef ONLY
X		{
X#ifdef FINDNEWNG
X		    bool doscan = (*buf == 'a');
X#endif
X
X		    if (!finish_command(TRUE)) /* get rest of command */
X			goto reinp_newsgroup;	/* if rubbed out, try something else */
X		    end_only();
X		    if (buf[1]) {
X			bool minusd = instr(buf+1,"-d", TRUE) != Nullch;
X
X			sw_list(buf+1);
X			if (minusd)
X			    cwd_check();
X			putchar('\n') FLUSH;
X#ifdef FINDNEWNG
X			if (doscan && maxngtodo)
X			    scanactive();
X#endif
X			emptyOnly = (*buf == 'o' && maxngtodo);
X		    }
X		    ng = 0;		/* simulate ^ */
X		    retry = FALSE;
X		    break;
X		}
X#else
X		    notincl("o");
X		    goto reask_newsgroup;
X#endif
X		case '&':
X		    if (switcheroo()) /* get rest of command */
X			goto reinp_newsgroup;	/* if rubbed out, try something else */
X		    goto reask_newsgroup;
X		case 'l': {		/* list other newsgroups */
X		    if (!finish_command(TRUE)) /* get rest of command */
X			goto reinp_newsgroup;	/* if rubbed out, try something else */
X		    for (s = buf+1; *s == ' '; s++);
X		    			/* skip leading spaces */
X		    sprintf(cmd_buf,"%s '%s'",filexp(NEWSGROUPS),s);
X		    resetty();
X		    if (doshell(sh,cmd_buf))
X#ifdef VERBOSE
X			IF(verbose)
X			    fputs("    (Error from newsgroups program)\n",
X				stdout) FLUSH;
X			ELSE
X#endif
X#ifdef TERSE
X			    fputs("(Error)\n",stdout) FLUSH;
X#endif
X		    noecho();
X		    crmode();
X		    goto reask_newsgroup;
X		}
X		case 'U': case '+':
X		case '.': case '=':
X		case 'y': case 'Y': case '\t': /* do normal thing */
X		    if (ng >= nextrcline) {
X			fputs("\nNot on a newsgroup.",stdout) FLUSH;
X			goto reask_newsgroup;
X		    } else if (*buf == '.') {	/* start command? */
X			if (!finish_command(FALSE)) /* get rest of command */
X			    goto reinp_newsgroup;
X			s = savestr(buf+1);  /* do_newsgroup will free it */
X		    } else {
X			s = buf;
X			if (*buf == '+' || *buf == 'U' || *buf == '=')
X			    *s++ = lastchar; /* restore 0200 if from a macro */
X			save_typeahead(s, sizeof buf - 1);
X			if (*buf)
X			    s = savestr(buf);
X			else
X			    s = Nullch;
X		    }
X		    if (toread[ng])
X			retry = TRUE;
X		    switch (do_newsgroup(s)) {
X		    case NG_ERROR:
X		    case NG_NORM:
X			ng++;
X			break;
X		    case NG_ASK:
X			goto reask_newsgroup;
X		    case NG_SELPRIOR:
X			*buf = 'p';
X			goto do_command;
X		    case NG_SELNEXT:
X			*buf = 'n';
X			goto do_command;
X		    case NG_MINUS:
X			ng = recent_ng;	/* recall previous newsgroup */
X			special = TRUE;	/* don't skip it if toread==0 */
X			break;
X		    }
X		    break;
X#ifdef STRICTCR
X		case '\n':
X		    fputs(badcr,stdout) FLUSH;
X		    goto reask_newsgroup;
X#endif
X		case 'v':
X		    putchar('\n');
X		    trn_version();
X		    goto reask_newsgroup;
X		default:
X		    printf("\n%s",hforhelp) FLUSH;
X		    settle_down();
X		    goto reask_newsgroup;
X		}
X	    }
X	    if (!retry)
X		break;
X#ifdef USE_NNTP
X	    if (actfp && actFetchTime
X	     && time(Null(time_t*)) - lastactfetch > actFetchTime) {
X		fclose(actfp);
X		printf("Grabbing new active file..."), fflush(stdout);
X		ngdata_init();	/* re-grab the active file */
X		carriage_return();
X		erase_eol();
X	    }
X#endif
X	}
X    }
X
X    /* now write .newsrc back out */
X
X    write_rc();
X
X    if (oh_for_the_good_old_days)
X	get_old_rc();
X
X    finalize(0);			/* and exit */
X}
X
Xvoid
Xtrn_version()
X{
X    printf("\nTrn version:%s.\nConfigured for ",patchlevel,rnid);
X#ifdef USE_NNTP
X    printf("NNTP news access.\n");
X#else
X    printf("Local news access.\n");
X#endif
X    printf("Send bug reports, suggestions, etc. to: davison@borland.com\n") FLUSH;
X}
X
X/* set current newsgroup */
X
Xvoid
Xset_ngname(what)
Xchar *what;
X{
X    int len = strlen(what)+1;
X
X    growstr(&ngname,&ngnlen,len);
X    strcpy(ngname,what);
X    growstr(&ngdir,&ngdlen,len);
X    strcpy(ngdir,getngdir(ngname));
X}
X
Xstatic char *myngdir;
Xstatic int ngdirlen = 0;
X
Xchar *
Xgetngdir(ngnam)
Xchar *ngnam;
X{
X    register char *s;
X
X    growstr(&myngdir,&ngdirlen,strlen(ngnam)+1);
X    strcpy(myngdir,ngnam);
X    for (s = myngdir; *s; s++)
X	if (*s == '.')
X	    *s = '/';
X    return myngdir;
X}
SHAR_EOF
  $shar_touch -am 1118220194 'trn-3.6/trn.c' &&
  chmod 0644 'trn-3.6/trn.c' ||
  echo 'restore of trn-3.6/trn.c failed'
  shar_count="`wc -c < 'trn-3.6/trn.c'`"
  test 16075 -eq "$shar_count" ||
    echo "trn-3.6/trn.c: original size 16075, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/trn.h ==============
if test -f 'trn-3.6/trn.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/trn.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/trn.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/trn.h' &&
X/* $Id: trn.h,v 4.4 1991/09/09 20:27:37 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
XEXT char *ngname INIT(Nullch);		/* name of current newsgroup */
XEXT int ngnlen INIT(0);			/* current malloced size of ngname */
XEXT char *ngdir INIT(Nullch);		/* same thing in directory name form */
XEXT int ngdlen INIT(0);			/* current malloced size of ngdir */
X
XEXT NG_NUM ng INIT(0);		/* current newsgroup index into rcline and toread */
XEXT NG_NUM current_ng INIT(0);	/* stable current newsgroup so we can ditz with ng */
XEXT NG_NUM starthere INIT(0);   /* set to the first newsgroup with unread news on startup */
XEXT char *spool INIT(Nullch);		/* public news spool directory */
XEXT char *threaddir INIT(Nullch);	/* directory for thread data */
XEXT char *overviewdir INIT(Nullch);	/* directory for overview data */
X
Xvoid	rn_init _((void));
Xvoid	main _((int,char**));
Xvoid	set_ngname _((char*));
Xchar	*getngdir _((char*));
Xvoid	trn_version _((void));
SHAR_EOF
  $shar_touch -am 1118220194 'trn-3.6/trn.h' &&
  chmod 0644 'trn-3.6/trn.h' ||
  echo 'restore of trn-3.6/trn.h failed'
  shar_count="`wc -c < 'trn-3.6/trn.h'`"
  test 1502 -eq "$shar_count" ||
    echo "trn-3.6/trn.h: original size 1502, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/unipatch.c ==============
if test -f 'trn-3.6/unipatch.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/unipatch.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/unipatch.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/unipatch.c' &&
X/*
XA filter to turn a unified diff into a degenerate context diff (no '!'s)
Xfor patch. Version 1.1. Author: davison@borland.com
X*/
X#include <stdio.h>
X#define ERR(a) {fputs(a,stderr);exit(1);}
X#define NUM(x) {for(x=0;*cp<='9'&&*cp>='0';)x=x*10+*cp++-'0';ch= *cp++;}
Xstruct Ln {struct Ln *lk; char t; char s[1];} r,*h,*ln;
Xchar bf[2048],*cp,ch,*malloc();
Xlong os,ol,ns,nl,ne,lncnt;
Xmain()
X{
X for(;;){
X  for(;;){
X   if(!fgets(bf,sizeof bf,stdin)) exit(0);
X   lncnt++;
X   if(!strncmp(bf,"@@ -",4)) break;
X   fputs(bf,stdout);
X  }
X  ol=nl=1, cp=bf+4;
X  NUM(os)
X  if(ch==',') NUM(ol)
X  if(*cp++!='+') goto bad;
X  NUM(ns)
X  if(ch==',') NUM(nl)
X  if(*cp!='@') goto bad;
X  r.lk=0, h= &r, ne=ns+nl-1;
X  printf("***************\n*** %ld,%ld ****\n",os,os+ol-(os>0));
X  while(ol||nl){
X   if(!fgets(bf,sizeof bf,stdin)){
X    if(nl>2) ERR("Unexpected end of file.\n")
X    strcpy(bf," \n");
X   }
X   lncnt++;
X   if(*bf=='\t'||*bf=='\n') ch=' ', cp=bf;
X   else ch= *bf, cp=bf+1;
X   switch(ch){
X   case'-':if(!ol--) goto bad;
X	printf("- %s",cp);
X	break;
X   case'=':ch=' ';
X   case' ':if(!ol--) goto bad;
X	printf("  %s",cp);
X   case'+':if(!nl--) goto bad;
X	ln = (struct Ln*)malloc(sizeof(*ln)+strlen(cp));
X	if(!ln) ERR("Out of memory!\n")
X	ln->lk=0, ln->t=ch, strcpy(ln->s,cp);
X	h->lk=ln, h=ln;
X	break;
X   default:
Xbad:	fprintf(stderr,"Malformed unified diff at line %ld: ",lncnt);
X	ERR(bf)
X   }
X  }
X  printf("--- %ld,%ld ----\n",ns,ne);
X  for(ln=r.lk;ln;ln=h){
X   printf("%c %s",ln->t,ln->s);
X   h=ln->lk; free(ln);
X  }
X }
X}
SHAR_EOF
  $shar_touch -am 1223090692 'trn-3.6/unipatch.c' &&
  chmod 0644 'trn-3.6/unipatch.c' ||
  echo 'restore of trn-3.6/unipatch.c failed'
  shar_count="`wc -c < 'trn-3.6/unipatch.c'`"
  test 1507 -eq "$shar_count" ||
    echo "trn-3.6/unipatch.c: original size 1507, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/unship.c ==============
if test -f 'trn-3.6/unship.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/unship.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/unship.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/unship.c' &&
X/* unship.c -- for unpacking ship files via trn */
X/* Based on ship.c -- Not copyrighted 1991 Mark Adler. */
X/* Modified by Wayne Davison, but still not copyrighted. */
X
X/* The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "respond.h"
X#include "decode.h"
X
Xtypedef unsigned long ulg;	/* 32-bit unsigned integer */
X
X/* Function prototypes */
X
Xstatic void decode_line _((unsigned char *));
Xstatic void err _((int));
X
X/* Globals for ship() */
Xulg ccnt;		/* count of bytes read or written */
Xulg crc;		/* CRC register */
Xulg buf4;		/* four byte buffer */
Xint bcnt;		/* buffer count */
X
Xunsigned int decb;	/* bit buffer for decode */
Xunsigned int decn;	/* number of bits in decb */
X
Xbool fast;		/* true for arithmetic coding, else base 85 */
Xbool overwrite = 1;	/* should we overwrite existing files? */
X
X/* Errors */
X#define SE_FORM 1
X#define SE_CONT 2
X#define SE_CRC 3
X#define SE_OVER 4
X#define SE_FULL 5
Xchar *errors[] = {
X  /* 1 */ "Invalid ship format.",
X  /* 2 */ "This piece is out of sequence.",
X  /* 3 */ "CRC check failed.",
X  /* 4 */ "File already exists.",
X  /* 5 */ "Error writing file.",
X};
X
X/* Set of 86 characters used for the base 85 digits (last one not used), and
X   the 86 character arithmetic coding.	Selected to be part of both the ASCII
X   printable characters, and the common EBCDIC printable characters whose
X   ASCII translations are universal. */
Xunsigned char safe[] = {
X	'{','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',
X	'0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?','@',
X	'A','B','C','D','E','F','G','H','I','J','K','L','M',
X	'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_',
X	'a','b','c','d','e','f','g','h','i','j','k','l','m',
X	'n','o','p','q','r','s','t','u','v','w','x','y','z','}'};
X
X#define LOWSZ (sizeof(safe)-64)		/* low set size for fast coding */
X
X/* Special replacement pairs--if first of each pair is received, it is
X   treated like the second member of the pair.	You're probably
X   wondering why.  The first pair is for compatibility with an
X   earlier version of ship that used ! for the base 85 zero digit.
X   However, there exist ASCII-EBCDIC translation tables that don't
X   know about exclamation marks.  The second set has mysterious
X   historical origins that are best left unspoken ... */
Xunsigned char aliases[] = {'!','{','|','+',0};
X
X/* Inverse of safe[], filled in by unship_init() */
Xunsigned char invsafe[256];
X
X/* Table of CRC-32's of all single byte values (made by makecrc.c) */
Xulg crctab[] = {
X  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
X  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
X  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
X  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
X  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
X  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
X  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
X  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
X  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
X  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
X  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
X  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
X  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
X  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
X  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
X  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
X  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
X  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
X  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
X  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
X  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
X  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
X  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
X  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
X  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
X  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
X  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
X  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
X  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
X  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
X  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
X  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
X  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
X  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
X  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
X  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
X  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
X  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
X  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
X  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
X  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
X  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
X  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
X  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
X  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
X  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
X  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
X  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
X  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
X  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
X  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
X  0x2d02ef8dL
X};
X
X/* Macro to update the CRC shift register one byte at a time */
X#define CRC(c,b) (crctab[((int)(c)^(int)(b))&0xff]^((c)>>8))
X
X/* cputc(d,x)--like putc(d,f), but delays four bytes and computes a CRC.
X   x is a cfile *, and d is expected to be an ulg. */
X#define cputf(fp) (int)(crc=CRC(crc,buf4),putc((int)buf4&0xff,fp),ccnt++)
X#define cputc(d,fp) (bcnt!=4?bcnt++:cputf(fp),buf4=(buf4>>8)+((ulg)(d)<<24))
X
X/* Build invsafe[], the inverse of safe[]. */
Xvoid
Xunship_init()
X{
X  int i;
X
X  for (i = 0; i < 256; i++)
X    invsafe[i] = 127;
X  for (i = 0; i < sizeof(safe); i++)
X    invsafe[safe[i]] = (char)i;
X  for (i = 0; aliases[i]; i += 2)
X    invsafe[aliases[i]] = invsafe[aliases[i + 1]];
X}
X
Xint
Xunship(in)
XFILE *in;
X{
X  int b;		/* state of line loop */
X  char l[LBUFLEN];	/* line buffer on input */
X  char *p;		/* modifies line buffer */
X  char *q;		/* scans continuation line */
X
X  /* Loop on the latest article's lines */
X  b = 2;				/* not in body yet */
X  while (1)				/* return on end of last file */
X  {
X    /* Get next line from file */
X    if (fgets(l, LBUFLEN, in) == Nullch)
X      break;
X
X    /* Strip control characters and leading blank space, if any */
X    for (q = l; *q && *q <= ' ' && *q != '\n'; q++)
X      ;
X    for (p = l; *q; q++)
X      if (*q >= ' ' || *q == '\n')
X	*p++ = *q;
X    *p = 0;
X
X    /* Based on current state, end or start on terminator.  States are:
X	 b == 0:  at start of body or body terminator line
X	 b == 1:  in middle of body line
X	 b == 2:  at start of non-body line
X	 b == 3:  in middle of non-body line
X	 b == 4:  at information line
X    */
X    switch (b)
X    {
X    case 0:
X      if ((!fast && strEQ(l, "$\n")) ||
X	  (fast && strEQ(l, "$ f\n")))
X      {
X	b = 4;
X	break;
X      }
X      /* fall through to case 1 */
X    case 1:
X      decode_line((unsigned char *)l);
X      b = l[strlen(l) - 1] != '\n';
X      break;
X    case 2:
X      if (strEQ(l, "$\n") || strEQ(l, "$ f\n"))
X      {
X	fast = l[1] == ' ';
X	b = 4;
X	break;
X      }
X      /* fall through to case 3 */
X    case 3:
X      b = l[strlen(l)-1] == '\n' ? 2 : 3;
X      break;
X    case 4:
X      /* Possible information lines are ship, more, cont, and end */
X      if (l[b = strlen(l) - 1] != '\n')
X      {
X	err(SE_FORM);
X	decode_end();
X	return -1;
X      }
X      l[b] = 0;
X      if (strnEQ(l, "ship ", 5))
X      {
X	/* get name, open new output file */
X	if (decode_fp != Nullfp)
X	  decode_end();			/* outputs an "incomplete" warning */
X	if (strEQ(l + 5, "-"))
X	  strcpy(decode_fname, "unnamed");
X	else
X	  strcpy(decode_fname, l + 5);
X	sprintf(decode_dest, "%s/%s", extractdest, decode_fname);
X	printf("Decoding: %s\n", decode_fname);
X#ifndef VMS	/* shouldn't have explicit version #, so VMS won't overwrite */
X	if (!overwrite && (decode_fp = fopen(decode_dest, "r")) != Nullfp)
X	{
X	  fclose(decode_fp);
X	  decode_fp = Nullfp;
X	  err(SE_OVER);
X	  return -1;
X	}
X#endif /* !VMS */
X	if ((decode_fp = fopen(decode_dest, FOPEN_WB)) == Nullfp)
X	{
X	  err(SE_FULL);
X	  return -1;
X	}
X	crc = 0xffffffffL;		/* preload CRC register */
X	buf4 = 0;			/* empty fifo (for output) */
X	bcnt = 0;			/* fifo is empty (output) */
X	b = decb = decn = 0;
X	ccnt = 0;
X      }
X      else if (strEQ(l, "more"))
X      {
X	/* check if currently writing */
X	if (decode_fp == Nullfp)
X	{
X	  err(SE_FORM);
X	  return -1;
X	}
X	b = 2;
X      }
X      else if (strnEQ(l, "cont ", 5))
X      {
X	/* check name and file offset */
X	if (decode_fp == Nullfp)
X	{
X	  err(SE_CONT);
X	  return -1;
X	}
X	for (q = l + 5; *q && *q != ' '; q++)
X	  ;
X	if (*q == 0 || atol(l + 5) != ccnt + 4 + (decn != 0) ||
X	    strNE(q + 1, decode_fname))
X	{
X	  err(SE_CONT);
X	  return -1;
X	}
X	b = 0;
X      }
X      else if (strcmp(l, "end") == 0)
X      {
X	/* check crc, close output file */
X	if (decode_fp == Nullfp)
X	{
X	  err(SE_FORM);
X	  return -1;
X	}
X	if (bcnt != 4 || buf4 != ~crc)
X	  err(SE_CRC);
X	else
X	  printf("CRC verified -- Done.\n");
X	if (ferror(decode_fp) || fclose(decode_fp))
X	{
X	  err(SE_FULL);
X	  decode_end();
X	  return -1;
X	}
X	decode_fp = Nullfp;
X	b = 2;
X      }
X      else
X      {
X	for (q = l; *q && *q != ' '; q++)
X	  ;
X	*q = 0;
X	printf("Ignoring unsupported ship keyword: '%s'\n", l);
X	b = 4;
X      }
X      break;
X    }
X  }
X  if (!(b & 2)) {
X    err(SE_FORM);
X    return -1;
X  }
X  if (decode_fp)
X    printf("(Continued)\n");
X  return 0;
X}
X
X/* Decode s, a string of base 85 digits or, if fast is true, a string of safe
X   characters generated arithmetically, into its binary equivalent, writing
X   the result to decode_fp, using cputc(). */
Xstatic void
Xdecode_line(s)
Xunsigned char *s;	/* data to decode */
X{
X  int b;		/* state of line loop, next character */
X  int k;		/* counts bits or digits read */
X  /* powers of 85 table for decoding */
X  static ulg m[] = {1L,85L,85L*85L,85L*85L*85L,85L*85L*85L*85L};
X
X  if (fast)
X  {
X    unsigned int d;	/* disperses bits */
X
X    d = decb;
X    k = decn;
X    while ((b = *s++) != 0)
X      if ((b = invsafe[b]) < sizeof(safe))
X      {
X	if (b < LOWSZ)
X	{
X	  d |= b << k;
X	  k += 7;
X	}
X	else if ((b -= LOWSZ) < LOWSZ)
X	{
X	  d |= (b + 0x40) << k;
X	  k += 7;
X	}
X	else
X	{
X	  d |= b << k;
X	  k += 6;
X	}
X	if (k >= 8)
X	{
X	  cputc(d, decode_fp);
X	  d >>= 8;
X	  k -= 8;
X	}
X      }
X    decb = d;
X    decn = k;
X  }
X  else
X  {
X    ulg d;		/* disperses bytes */
X
X    d = k = 0;
X    while ((b = *s++) != 0)
X      if ((b = invsafe[b]) < 85)
X      {
X	d += m[k] * b;
X	if (++k == 5)
X	{
X	  cputc(d, decode_fp);  d >>= 8;
X	  cputc(d, decode_fp);  d >>= 8;
X	  cputc(d, decode_fp);  d >>= 8;
X	  cputc(d, decode_fp);
X	  d = k = 0;
X	}
X      }
X    if (--k > 0)
X    {
X      while (--k)
X      {
X	cputc(d, decode_fp);
X	d >>= 8;
X      }
X      cputc(d, decode_fp);
X    }
X  }
X}
X
Xstatic void
Xerr(n)
Xint n;			/* error number */
X{
X  if (n == SE_FULL)
X    perror("ship");
X  fputs(errors[n - 1], stdout);
X  putchar('\n') FLUSH;
X}
SHAR_EOF
  $shar_touch -am 0508212994 'trn-3.6/unship.c' &&
  chmod 0644 'trn-3.6/unship.c' ||
  echo 'restore of trn-3.6/unship.c failed'
  shar_count="`wc -c < 'trn-3.6/unship.c'`"
  test 11878 -eq "$shar_count" ||
    echo "trn-3.6/unship.c: original size 11878, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/util.c ==============
if test -f 'trn-3.6/util.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/util.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/util.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/util.c' &&
X/* $Id: util.c,v 3.0 1992/02/23 21:25:39 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "final.h"
X#include "term.h"
X#include "nntp.h"
X#include "nntpauth.h"
X#include "INTERN.h"
X#include "util.h"
X
Xvoid
Xutil_init()
X{
X    ;
X}
X    
X/* fork and exec a shell command */
X
Xint
Xdoshell(shl,s)
Xchar *s, *shl;
X{
X    int status, pid, w;
X    char *shell;
X    bool mouse_flag;	/* if TRUE, mouse tracking was on */
X
X    mouse_flag = xmouse_status;
X    xmouse_off();
X
X#ifdef SIGTSTP
X    sigset(SIGTSTP,SIG_DFL);
X    sigset(SIGTTOU,SIG_DFL);
X    sigset(SIGTTIN,SIG_DFL);
X#endif
X    if (shl != Nullch)
X	shell = shl;
X    else if ((shell = getenv("SHELL")) == Nullch || !*shell)
X	shell = PREFSHELL;
X    if ((pid = vfork()) == 0) {
X#ifdef USE_NNTP
X        int i;
X
X	/* This is necessary to keep bourne shell from puking */
X
X        for (i = 3; i < 10; ++i) {
X#ifdef USE_GENAUTH
X	    if (cookiefd != -1) {
X		if (i == fileno(ser_rd_fp)
X		 || i == fileno(ser_wr_fp)
X		 || i == cookiefd)
X		    continue;
X	    }
X#endif
X            close(i);
X	}
X#endif /* USE_NNTP */
X
X	if (*s)
X	    execl(shell, shell, "-c", s, Nullch);
X	else
X	    execl(shell, shell, Nullch, Nullch, Nullch);
X	_exit(127);
X    }
X    signal(SIGINT, SIG_IGN);
X#ifdef SIGQUIT
X    signal(SIGQUIT, SIG_IGN);
X#endif 
X    termlib_reset();
X    waiting = TRUE;
X    while ((w = wait(&status)) != pid)
X	if (w == -1 && errno != EINTR)
X	    break;
X    if (w == -1)
X	status = -1;
X    termlib_init();
X    if (mouse_flag)
X	xmouse_on();
X    waiting = FALSE;
X    sigset(SIGINT, int_catcher);	/* always catch interrupts */
X#ifdef SIGQUIT
X    signal(SIGQUIT, SIG_DFL);
X#endif 
X#ifdef SIGTSTP
X    sigset(SIGTSTP,stop_catcher);
X    sigset(SIGTTOU,stop_catcher);
X    sigset(SIGTTIN,stop_catcher);
X#endif
X    return status;
X}
X
Xstatic char nomem[] = "trn: out of memory!\n";
X
X/* paranoid version of malloc */
X
Xchar *
Xsafemalloc(size)
XMEM_SIZE size;
X{
X    char *ptr;
X
X    ptr = malloc(size ? size : (MEM_SIZE)1);
X    if (ptr == Nullch) {
X	fputs(nomem,stdout) FLUSH;
X	sig_catcher(0);
X    }
X    return ptr;
X}
X
X/* paranoid version of realloc.  If where is NULL, call malloc */
X
Xchar *
Xsaferealloc(where,size)
Xchar *where;
XMEM_SIZE size;
X{
X    char *ptr;
X
X    if (!where)
X	ptr = malloc(size ? size : (MEM_SIZE)1);
X    else
X	ptr = realloc(where, size ? size : (MEM_SIZE)1);
X    if (!ptr) {
X	fputs(nomem,stdout) FLUSH;
X	sig_catcher(0);
X    }
X    return ptr;
X}
X
X/* safe version of string copy */
X
Xchar *
Xsafecpy(to,from,len)
Xchar *to;
Xregister char *from;
Xregister int len;
X{
X    register char *dest = to;
X
X    if (from != Nullch) 
X	for (len--; len && (*dest++ = *from++); len--) ;
X    *dest = '\0';
X    return to;
X}
X
X/* safe version of string concatenate, with \n deletion and space padding */
X
Xchar *
Xsafecat(to,from,len)
Xchar *to;
Xregister char *from;
Xregister int len;
X{
X    register char *dest = to;
X
X    len--;				/* leave room for null */
X    if (*dest) {
X	while (len && *dest++) len--;
X	if (len) {
X	    len--;
X	    *(dest-1) = ' ';
X	}
X    }
X    if (from != Nullch)
X	while (len && (*dest++ = *from++)) len--;
X    if (len)
X	dest--;
X    if (*(dest-1) == '\n')
X	dest--;
X    *dest = '\0';
X    return to;
X}
X
X/* copy a string up to some (non-backslashed) delimiter, if any */
X
Xchar *
Xcpytill(to,from,delim)
Xregister char *to, *from;
Xregister int delim;
X{
X    for (; *from; from++,to++) {
X	if (*from == '\\' && from[1] == delim)
X	    from++;
X	else if (*from == delim)
X	    break;
X	*to = *from;
X    }
X    *to = '\0';
X    return from;
X}
X
X/* effective access */
X
X#ifdef SETUIDGID
Xint
Xeaccess(filename, mod)
Xchar *filename;
Xint mod;
X{
X    int protection, euid;
X    
X    mod &= 7;				/* remove extraneous garbage */
X    if (stat(filename, &filestat) < 0)
X	return -1;
X    euid = geteuid();
X    if (euid == ROOTID)
X	return 0;
X    protection = 7 & (filestat.st_mode >>
X      (filestat.st_uid == euid ? 6 :
X        (filestat.st_gid == getegid() ? 3 : 0)
X      ));
X    if ((mod & protection) == mod)
X	return 0;
X    errno = EACCES;
X    return -1;
X}
X#endif
X
X/*
X * Get working directory
X */
X#ifndef HAS_GETWD
X#ifdef HAS_GETCWD
Xchar *
Xgetwd(np)
Xchar *np;
X{
X    char *ret;
X    extern char *getcwd();
X
X    if ((ret = getcwd(np,512)) == Nullch) {
X	printf("Cannot determine current working directory!\n") FLUSH;
X	finalize(1);
X    }
X    return ret;
X}
X#else
Xchar *
Xgetwd(np)
Xchar *np;
X{
X    FILE *popen();
X    FILE *pipefp;
X
X    if ((pipefp = popen("/bin/pwd","r")) == Nullfp) {
X	printf("Can't run /bin/pwd\n") FLUSH;
X	finalize(1);
X    }
X    fgets(np,512,pipefp);
X    np[strlen(np)-1] = '\0';	/* wipe out newline */
X    if (pclose(pipefp) == EOF) {
X	printf("Failed to run /bin/pwd\n") FLUSH;
X	finalize(1);
X    }
X    return np;
X}
X#endif
X#endif
X
X/* just like fgets but will make bigger buffer as necessary */
X
Xchar *
Xget_a_line(buffer,buffer_length,realloc_ok,fp)
Xchar *buffer;
Xregister int buffer_length;
Xbool_int realloc_ok;
XFILE *fp;
X{
X    register int bufix = 0;
X    register int nextch;
X
X    do {
X	if (bufix >= buffer_length) {
X	    buffer_length *= 2;
X	    if (realloc_ok) {		/* just grow in place, if possible */
X		buffer = saferealloc(buffer,(MEM_SIZE)buffer_length+1);
X	    }
X	    else {
X		char *tmp = safemalloc((MEM_SIZE)buffer_length+1);
X		strncpy(tmp,buffer,buffer_length/2);
X		buffer = tmp;
X		realloc_ok = TRUE;
X	    }
X	}
X	if ((nextch = getc(fp)) == EOF)
X	    return Nullch;
X	buffer[bufix++] = (char)nextch;
X    } while (nextch && nextch != '\n');
X    buffer[bufix] = '\0';
X    len_last_line_got = bufix;
X    buflen_last_line_got = buffer_length;
X    return buffer;
X}
X
X/* copy a string to a safe spot */
X
Xchar *
Xsavestr(str)
Xchar *str;
X{
X    register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
X
X    strcpy(newaddr,str);
X    return newaddr;
X}
X
Xint
Xmakedir(dirname,nametype)
Xregister char *dirname;
Xint nametype;
X{
X#ifdef MAKEDIR
X    register char *end;
X    register char *s;
X    char tmpbuf[1024];
X    register char *tbptr = tmpbuf+5;
X
X    for (end = dirname; *end; end++) ;	/* find the end */
X    if (nametype == MD_FILE) {		/* not to create last component? */
X	for (--end; end != dirname && *end != '/'; --end) ;
X	if (*end != '/')
X	    return 0;			/* nothing to make */
X	*end = '\0';			/* isolate file name */
X    }
X    strcpy(tmpbuf,"mkdir");
X
X    s = end;
X    for (;;) {
X	if (stat(dirname,&filestat) >= 0 && S_ISDIR(filestat.st_mode)) {
X					/* does this much exist as a dir? */
X	    *s = '/';			/* mark this as existing */
X	    break;
X	}
X	s = rindex(dirname,'/');	/* shorten name */
X	if (!s)				/* relative path! */
X	    break;			/* hope they know what they are doing */
X	*s = '\0';			/* mark as not existing */
X    }
X    
X    for (s=dirname; s <= end; s++) {	/* this is grody but efficient */
X	if (!*s) {			/* something to make? */
X	    sprintf(tbptr," %s",dirname);
X	    tbptr += strlen(tbptr);	/* make it, sort of */
X	    *s = '/';			/* mark it made */
X	}
X    }
X    if (nametype == MD_DIR)		/* don't need final slash unless */
X	*end = '\0';			/*  a filename follows the dir name */
X
X    return (tbptr==tmpbuf+5 ? 0 : doshell(sh,tmpbuf));
X					/* exercise our faith */
X#else
X    sprintf(cmd_buf,"%s %s %d", filexp(DIRMAKER), dirname, nametype);
X    return doshell(sh,cmd_buf);
X#endif
X}
X
Xvoid
Xnotincl(feature)
Xchar *feature;
X{
X    printf("\nNo room for feature \"%s\" on this machine.\n",feature) FLUSH;
X}
X
Xchar *
Xgetval(nam,def)
Xchar *nam,*def;
X{
X    char *val;
X
X    if ((val = getenv(nam)) == Nullch || !*val)
X	val = def;
X    return val;
X}
X
X/* grow a static string to at least a certain length */
X
Xvoid
Xgrowstr(strptr,curlen,newlen)
Xchar **strptr;
Xint *curlen;
Xint newlen;
X{
X    if (newlen > *curlen) {		/* need more room? */
X	if (*curlen)
X	    *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
X	else
X	    *strptr = safemalloc((MEM_SIZE)newlen);
X	*curlen = newlen;
X    }
X}
X
Xvoid
Xsetdef(buffer,dflt)
Xchar *buffer,*dflt;
X{
X#ifdef STRICTCR
X    if (*buffer == ' ')
X#else
X    if (*buffer == ' ' || *buffer == '\n')
X#endif
X    {
X	if (*dflt == '^' && isupper(dflt[1]))
X	    pushchar(Ctl(dflt[1]));
X	else
X	    pushchar(*dflt);
X	getcmd(buffer);
X    }
X}
X
Xvoid
Xsafelink(old, new)
Xchar *old, *new;
X{
X#if 0
X    extern int sys_nerr;
X    extern char *sys_errlist[];
X#endif
X
X    if (link(old,new)) {
X	printf("Can't link backup (%s) to .newsrc (%s)\n", old, new) FLUSH;
X#if 0
X	if (errno>0 && errno<sys_nerr)
X	    printf("%s\n", sys_errlist[errno]);
X#endif
X	finalize(1);
X    }
X}
SHAR_EOF
  $shar_touch -am 1028162094 'trn-3.6/util.c' &&
  chmod 0644 'trn-3.6/util.c' ||
  echo 'restore of trn-3.6/util.c failed'
  shar_count="`wc -c < 'trn-3.6/util.c'`"
  test 8885 -eq "$shar_count" ||
    echo "trn-3.6/util.c: original size 8885, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/util.h ==============
if test -f 'trn-3.6/util.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/util.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/util.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/util.h' &&
X/* $Id: util.h,v 3.0 1991/09/09 20:27:37 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
XEXT bool waiting INIT(FALSE);	
X			/* are we waiting for subprocess (in doshell)? */
XEXT int len_last_line_got INIT(0);
X			/* strlen of some_buf after */
X			/*  some_buf = get_a_line(bufptr,bufsize,realloc,fp) */
XEXT MEM_SIZE buflen_last_line_got INIT(0);
X
X/* is the string for makedir a directory name or a filename? */
X
X#define MD_DIR 	0
X#define MD_FILE 1
X
Xvoid	util_init _((void));
Xint	doshell _((char*,char*));
Xchar	*safemalloc _((MEM_SIZE));
Xchar	*saferealloc _((char*,MEM_SIZE));
Xchar	*safecpy _((char*,char*,int));
Xchar	*safecat _((char*,char*,int));
Xchar	*cpytill _((char*,char*,int));
X#ifdef SETUIDGID
Xint	eaccess _((char*,int));
X#endif
Xchar	*getwd _((char*));
Xchar	*get_a_line _((char*,int,bool_int,FILE*));
Xchar	*savestr _((char*));
Xint	makedir _((char*,int));
Xvoid	notincl _((char*));
Xchar	*getval _((char*,char*));
Xvoid	growstr _((char**,int*,int));
Xvoid	setdef _((char*,char*));
Xvoid	safelink _((char*,char*));
SHAR_EOF
  $shar_touch -am 1028162094 'trn-3.6/util.h' &&
  chmod 0644 'trn-3.6/util.h' ||
  echo 'restore of trn-3.6/util.h failed'
  shar_count="`wc -c < 'trn-3.6/util.h'`"
  test 1573 -eq "$shar_count" ||
    echo "trn-3.6/util.h: original size 1573, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/uudecode.c ==============
if test -f 'trn-3.6/uudecode.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/uudecode.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/uudecode.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/uudecode.c' &&
X/* $Id: uudecode.c,v 4.4.3.1 1992/02/01 03:09:32 $
X * 
X * Decode one or more uuencoded articles back to binary form.
X * Trn version created by Wayne Davison.
X * Formerly the nn version by Kim Storm.
X * From the Berkeley original, modified by MSD, RDR, JPHD & WLS.
X */
X/*
X * This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "respond.h"
X#include "decode.h"
X
X#define MAXCHAR 256
X#define NORMLEN 64	/* allows for 84 encoded chars per line */
X
X#define SEQMAX 'z'
X#define SEQMIN 'a'
X
Xstatic char seqc;
Xstatic int first, secnd, check, numl;
X
Xstatic char blank;
Xstatic int chtbl[MAXCHAR], cdlen[NORMLEN + 3];
Xstatic int state;
Xstatic bool Xflag;
Xstatic int expecting_part;
X
Xstatic int decode_line _((char *));
Xstatic void inittbls _((void));
Xstatic void gettable _((FILE *));
X
X#define	NO_ADVANCE		0x10
X
X#define	FIND_BEGIN		0x01
X#define	AFTER_ERROR_FIND_BEGIN	0x02
X#define	DECODE_TEXT		0x03
X#define	SKIP_TRAILING	       (0x04 | NO_ADVANCE)
X#define	SKIP_LEADING		0x05
X#define	FOUND_END	       (0x06 | NO_ADVANCE)
X#define DECODE_ERROR	       (0x07 | NO_ADVANCE)
X#define OTHER_ERROR	       (0x08 | NO_ADVANCE)
X#define NEW_BEGIN	       (0x09 | NO_ADVANCE)
X
Xvoid
Xuud_start()
X{
X    Xflag = FALSE;
X    expecting_part = 0;
X    seqc = SEQMAX;
X    check = 1;
X    first = 1;
X    secnd = 0;
X    state = FIND_BEGIN;
X}
X
Xint
Xuudecode(in)
XFILE *in;
X{
X    int mode, onedone, lens;
X    char buff[LBUFLEN];
X
X    numl = onedone = 0;
X
X    if (state == FIND_BEGIN)
X	inittbls();
X
X    /*
X     * search for header or translation table line.
X     */
X
X    while ((state & NO_ADVANCE) || fgets(buff, sizeof buff, in) != Nullch) {
X	numl++;
X
X	switch (state) {
X	 case NEW_BEGIN:
X	    if (decode_fp != Nullfp) {
X		if (expecting_part) {
X		    register int got_part = 0;
X
X		    if (strnEQ(buff + 6, "part ", 5)) {
X			register char *bp;
X
X			for (bp = buff + 11; islower(*bp); bp++)
X			    got_part = got_part * 26 + *bp - 'a';
X		    }
X		    if (expecting_part == got_part) {
X			state = DECODE_TEXT;
X			break;
X		    }
X		    printf("Expecting part %d; got part %d.\n",
X			 expecting_part + 1, got_part + 1);
X		    if (got_part) {
X			state = SKIP_LEADING;
X			return -1;
X		    }
X		}
X		decode_end();
X		sleep(2);
X		Xflag = FALSE;
X		expecting_part = 0;
X	    }
X	    state = FIND_BEGIN;
X	    /* fall thru */
X
X	 case FIND_BEGIN:
X	 case AFTER_ERROR_FIND_BEGIN:
X	    if (strnEQ(buff, "table", 5)) {
X		gettable(in);
X		continue;
X	    }
X
X	    if (strnEQ(buff, "begin ", 6)
X	     || strnEQ(buff, "Xbegin ", 7)) {
X		lens = strlen(buff)-1;
X		if (buff[lens] == '\n')
X		    buff[lens] = '\0';
X
X		if(sscanf(buff+6,"%o%s", &mode, decode_fname) != 2) {
X		    register char *bp = buff + 6;
X
X		    if (*bp == ' ')
X			bp++;
X		    if (strnEQ(bp, "part ", 5)) {
X			register int got_part = 0;
X
X			for (bp = bp + 5; islower(*bp); bp++)
X			    got_part = got_part * 26 + *bp - 'a';
X			printf("Expecting part 1; got part %d.\n",
X				got_part + 1);
X			return -1;
X		    }
X		    continue;
X		}
X
X		Xflag = (*buff == 'X');
X
X		sprintf(decode_dest, "%s/%s", extractdest, decode_fname);
X
X		if ((decode_fp = fopen(decode_dest, FOPEN_WB)) == Nullfp) {
X		    printf("Cannot create file: %s\n", decode_dest);
X		    goto err;
X		}
X		chmod(decode_dest, mode);
X		printf("Decoding: %s\n", decode_fname);
X		state = DECODE_TEXT;
X	    }
X	    continue;
X
X	 case SKIP_LEADING:
X	    state = decode_line(buff);
X	    continue;
X
X	 case DECODE_TEXT:
X	    state = decode_line(buff);
X	    onedone = 1;
X	    continue;
X
X	 case FOUND_END:
X	    fclose(decode_fp);
X	    decode_fp = Nullfp;
X	    Xflag = FALSE;
X	    expecting_part = 0;
X	    state = FIND_BEGIN;
X	    printf("Done.\n");
X	    continue;
X
X	 case SKIP_TRAILING:
X	    printf("(Continued)\n");
X	    state = SKIP_LEADING;
X	    return 0;
X
X	 case DECODE_ERROR:
X	    state = SKIP_TRAILING;
X	    continue;
X
X	 case OTHER_ERROR:
X	    fclose(decode_fp);
X	    decode_fp = Nullfp;
X	    Xflag = FALSE;
X	    expecting_part = 0;
X	    state = AFTER_ERROR_FIND_BEGIN;
X	    goto err;
X	}
X    }
X
X    if (onedone) {
X	if (state == DECODE_TEXT) {
X	    printf("(Continued)\n");
X	    state = SKIP_LEADING;
X	}
X	return 0;
X    }
X
X    if (state == AFTER_ERROR_FIND_BEGIN)
X	return -1;
X    printf("Couldn't find anything to decode.\n");
X
X err:
X    sleep(2);
X    return -1;
X}
X
X/*
X * decode one line and write it out using decode_fp
X */
X
Xstatic int
Xdecode_line(buff)
Xchar *buff;
X{
X    char outl[LBUFLEN];
X    register char *bp, *ut;
X    register int *trtbl = chtbl;
X    register int n;
X    register int blen;		/* binary length (from decoded file) */
X    register int rlen;		/* calculated input line length */
X    register int len;		/* actual input line length */
X    register int dash;		/* number of '-'s encountered on a line */
X				/* If it's too high, we reject the line */
X
X#   define REJECT(buf,rlen,len) \
X	((*buf == 'M' && len > rlen + 5) \
X	 || (*buf != 'M' && len != rlen && len != rlen+1) \
X	 || (strnEQ(buf, "BEGIN", 5)) \
X	 || (strnEQ(buf, "END", 3)))
X
X    if (Xflag) {
X	if (*buff == 'X')
X	    buff++;
X	else
X	    *buff = 'x';	/* force a mis-parse of a non-x'ed line */
X    }
X    len = strlen(buff);
X    if (--len <= 0)
X	return state;
X
X    buff[len] = '\0';
X
X    /*
X     * Get the binary line length.
X     */
X    if ((blen = trtbl[buff[0]]) < 0) {
X	if (state == SKIP_LEADING) {
X	    if (strnEQ(buff, "begin ", 6))
X		return NEW_BEGIN;
X
X	    return SKIP_LEADING;
X	}
X	/*
X	 * end of uuencoded file ?
X	 */
X	if (strnEQ(buff, "end", 3))
X	    return FOUND_END;
X
X	/*
X	 * end of current file ? : get next one.
X	 */
X	if (strnEQ(buff, "include ", 8)) {
X	    for (bp = buff + 8; *bp; bp++) {
X		if (bp[0] == '.' && bp[1] == 'u') {
X		    expecting_part = (bp[2] - 'a') * 26 + bp[3] - 'a';
X		    break;
X		}
X	    }
X	}
X
X	/*
X	 * trailing garbage
X	 */
X	return SKIP_TRAILING;
X    }
X
X    rlen = cdlen[blen];
X    if (state == SKIP_LEADING && REJECT(buff,rlen,len))
X	return SKIP_LEADING;
X
X    /*
X     * Is it the empty line before the end line ?
X     */
X    if (blen == 0)
X	return state;
X
X    if (REJECT(buff,rlen,len))
X	return SKIP_TRAILING;
X
X    /*
X     * Pad with blanks.
X     */
X    for (bp = buff + len, n = rlen - len; --n >= 0; )
X	*bp++ = blank;
X
X    /*
X     * Verify
X     */
X    for (n = rlen, bp = buff, dash = 0; --n >= 0; bp++) {
X	if (trtbl[*bp] < 0) {
X	    if (state == SKIP_LEADING)
X		return SKIP_LEADING;
X	    return DECODE_ERROR;
X	}
X	if (*bp == '-')
X	    dash++;
X    }
X    if (dash * 100 / rlen > 33)		/* more than 1/3 dashes? */
X	if (state == SKIP_LEADING)
X	    return SKIP_LEADING;	/* -> reject */
X	else
X	    return SKIP_TRAILING;
X
X    /*
X     * Check for uuencodes that append a 'z' to each line....
X     */
X    if (check)
X	if (secnd) {
X	    secnd = 0;
X	    if (buff[rlen] == SEQMAX)
X		check = 0;
X	} else if (first) {
X	    first = 0;
X	    secnd = 1;
X	    if (buff[rlen] != SEQMAX)
X		check = 0;
X	}
X
X    /*
X     * There we check.
X     */
X    if (check) {
X	if (buff[rlen] != seqc) {
X	    if (state == SKIP_LEADING)
X		return SKIP_LEADING;
X	    return DECODE_ERROR;
X	}
X
X	if (--seqc < SEQMIN)
X	    seqc = SEQMAX;
X    }
X
X    /*
X     * output a group of 3 bytes (4 input characters).
X     * the input chars are pointed to by p, they are to
X     * be output to file f. blen is used to tell us not to
X     * output all of them at the end of the file.
X     */
X    ut = outl;
X    n = blen;
X    bp = &buff[1];
X    while (--n >= 0) {
X	*(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
X	if (n > 0) {
X	    *(ut++) = (trtbl[bp[1]] << 4) | (trtbl[bp[2]] >> 2);
X	    n--;
X	}
X	if (n > 0) {
X	    *(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
X	    n--;
X	}
X	bp += 4;
X    }
X    if ((int)fwrite(outl, 1, blen, decode_fp) <= 0) {
X	printf("Error on writing decoded file\n");
X	return OTHER_ERROR;
X    }
X
X    return DECODE_TEXT;
SHAR_EOF
  : || echo 'restore of trn-3.6/uudecode.c failed'
fi
echo 'End of archive part 10'
echo 'File trn-3.6/uudecode.c is continued in part 11'
echo 11 > _sharseq.tmp
exit 0


