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= ' ') 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 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 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 _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