[comp.sources.unix] v19i076: NN, a Usenet news reader, Part15/15

rsalz@uunet.uu.net (Rich Salz) (06/27/89)

Submitted-by: storm@texas.dk (Kim F. Storm)
Posting-number: Volume 19, Issue 76
Archive-name: nn/part15

#!/bin/sh
# this is part 15 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file term.c continued
#
CurArch=15
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file term.c"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' >> term.c
X		    if ((comp_used = (*completion)(buf, i)) == 0) {
X			ding();
X			continue;
X		    }
X		    if (comp_used < 0) {
X			comp_used = 0;
X			goto no_completion;
X		    }
X		    comp_len = 0;
X		}
X		if (c == help_key) {
X		    if ((*completion)((char *)NULL, 1)) {
X			gotoxy(prompt_length+i, prompt_line); fl;
X			did_help = 1;
X		    }
X		    continue;
X		}
X		
X		if (comp_len) {
X		    i -= comp_len;
X		    while (--comp_len >= 0) putchar(BS);
X		    clrline();
X		    comp_len = 0;
X		}
X		
X		switch ( (*completion)((char *)NULL, 0) ) {
X
X		 case 0:	/* no possible completion */
X		    comp_used = 0;
X		    ding();
X		    continue;
X		    
X		 case 2:	/* whole new alternative */
X		    while (--i >= 0) putchar(BS);
X		    clrline();
X		    /* fall thru */
X
X		 case 1:	/* completion */
X		    comp_len = i;
X		    while (c = buf[i]) {
X			if (i == max) break;
X			putchar(c);
X			i++;
X		    }
X		    fl;
X		    comp_len = i - comp_len;
X		    continue;
X		}
X	    }
X
X	    if (comp_used) {
X		(*completion)(buf, -1);
X		if (did_help) clrmsg(i);
X		comp_len = comp_used = 0;
X	    }
X	}
X	
X     no_completion:
X
X	if (c == CR || c == NL) {
X	    buf[i] = NUL;
X	    break;
X	}
X	
X	if (c == erase_key) {
X	    if (i <= 0) continue;
X	    i--;
X	    putchar(BS);
X	    putchar(' ');
X	    putchar(BS);
X	    fl;
X	    continue;
X	}
X
X	if (c == delword_key) {
X	    if (i <= 0) continue;
X	    buf[i-1] = 'X';
X	    while (i > 0 && isalnum(buf[i-1])) { putchar(BS); i--; }
X	    clrline();
X	    continue;
X	}
X	
X	if (c == kill_key) {
X	    while (i > 0) { putchar(BS); i--; }
X	    clrline();
X	    if (hit_count == 1 && dflt) {
X		c = comp1_key;
X		goto kill_prefill_hack;
X	    }
X	    continue;
X	}
X	
X	if (c == K_interrupt) {
X	    ret_val = NULL;
X	    break;
X	}
X	
X	if (c < SP) continue;
X	
X	if (i == max) continue;
X
X	if (i > 0 && buf[i-1] == '/' && (c == '/' || c == '+')) {
X	    while (i > 0) { putchar(BS); i--; }
X	    clrline();
X	}	    
X
X	putchar(c);
X	fl;
X
X	buf[i] = c;
X	i++;
X    }
X out:
X    enable_stop = ostop;
X    do_macro_processing = 1;
X    return ret_val;
X}
X
Xexport int list_offset = 0;
X
Xlist_completion(str)
Xchar *str;
X{
X    static int cols, line;
X    
X    if (str == NULL) {
X	cols = Columns;
X	line = prompt_line + 1;
X    
X	gotoxy(0, line);
X	clrpage(line);
X	return 1;
X    }
X
X    str += list_offset;
X    
X    for (;;) {
X	cols -= strlen(str);
X	if (cols >= 0) {
X	    printf("%s%s", str, cols > 0 ? " " : "");
X	    cols--;
X	    return 1;
X	}
X	if (line >= Lines - 1) return 0;
X	line++;
X	cols = Columns;
X	gotoxy(0, line);
X	if (line == Lines - 1) cols--;
X    }
X}
X
Xyes(must_answer)
Xint must_answer;
X{
X    int c, help = 1, in_macro = 0;
X
X    switch (m_yes()) {
X     case 0:
X	break;
X     case 1:
X	return 0;
X     case 2:
X	return 1;
X     case 3:
X	do_macro_processing = 0;
X    	in_macro++;
X	break;
X    }
X
X    for (;;) {
X	if (!is_raw) {
X	    raw();
X	    c = get_c();
X	    no_raw();
X	} else
X	    c = get_c();
X
X	if (c == 'y' || c == 'Y') {
X	    c = 1;
X	    break;
X	}
X	
X	if (must_answer == 0 && (c == SP || c == CR || c == NL)) break;
X	if (c == 'n' || c == 'N') {
X	    c = 0;
X	    break;
X	}	
X	if (c == K_interrupt) {
X	    c = -1;
X	    break;
X	}
X	if (help) {
X	    fputs(" y=YES n=NO", stdout);
X	    prompt_length += 11;
X	    help = 0;
X	}
X    }
X
X    if (in_macro) {
X	if (c <= 0) m_break();
X	do_macro_processing = 1;
X    }
X    
X    return c;
X}
X
X
Xding()
X{
X    putp(bell);
X    fl;
X}
X
X
Xdisplay_file(name, modes)
Xchar *name;
Xint modes;
X{
X    FILE *f;
X    register c, stand_on;
X    int was_raw, linecnt, headln_cnt, hdline, no_conf;
X    char headline[128];
X    
X    headline[0] = 0;
X    hdline = 0;
X    no_conf = 0;
X    
X    headln_cnt = -1;
X    
X    was_raw = is_raw;
X
X    no_raw();
X
X    if (modes & CLEAR_DISPLAY) {
X	gotoxy(0,0);
X	clrdisp();
X    }
X    
X    linecnt = Lines - 1;
X
Xchain:    
X
X    f = open_file(relative(lib_directory, name), OPEN_READ);
X    if (f == NULL)
X	printf("\r\n\nFile %s is not available\n\n", name);
X    else {
X	stand_on = 0;
X    
X	while ((c = getc(f)) != EOF) {
X#ifdef HAVE_JOBCONTROL
X	    if (s_redraw) {
X		no_conf = 1;
X		break;
X	    }
X#endif	    
X	    no_conf = 0;
X	    if (c == '\1') {
X		if (STANDOUT) {
X		    putp(stand_on ? exit_standout_mode : enter_standout_mode);
X		    stand_on = !stand_on;
X		}
X		continue;
X	    }
X	    if (c == '\2') {
X		headln_cnt = 0;
X		continue;
X	    }
X	    if (c == '\3') {
X		headln_cnt = 0;
X		while ((c = getc(f)) != EOF && c != NL)
X		    headline[headln_cnt++] = c;
X		headline[headln_cnt++] = NUL;
X		name = headline;
X		fclose(f);
X		goto chain;
X	    }
X
X	    if (headln_cnt >= 0)
X		headline[headln_cnt++] = c;
X
X	    if (hdline) {
X		puts(headline);
X		hdline = 0;
X		linecnt--;
X	    }
X	    
X	    putchar(c);
X	    if (c == NL) {
X		if (headln_cnt >= 0) {
X		    headline[--headln_cnt] = 0;
X		    headln_cnt = -1;
X		}
X		if (--linecnt == 0) {
X		    no_conf = 1;
X		    if (any_key(0) == K_interrupt) 
X			break;
X		    linecnt = Lines - 1;
X		    if (modes & CLEAR_DISPLAY) {
X			gotoxy(0,0);
X			clrdisp();
X		    }
X		    hdline = headline[0];
X		}
X	    }
X	}
X	
X	if (stand_on) putp(exit_standout_mode);
X	fclose(f);
X    }
X
X    if (was_raw) raw();
X
X    prompt_line = Lines-1;	/* move prompt to last line */
X    
X    if (!no_conf && (modes & CONFIRMATION)) 
X	any_key(prompt_line);
X}
X
X
X/*VARARGS*/
Xuser_error(va_alist)
Xva_dcl
X{
X    char *fmt;
X    va_list ap;
X    
X    no_raw();
X    clrdisp();
X    fl;
X
X    va_start(ap);
X    fmt = va_arg1(char *);
X    
X    vprintf(fmt, va_args2toN);
X    putchar(NL);
X
X    va_end(ap);
X    nn_exit(1);
X}
X
X/*VARARGS*/
Xmsg(va_alist)
Xva_dcl
X{
X    va_list ap;
X    
X    va_start(ap);
X    vmsg(va_args1toN);
X    va_end(ap);
X}
X
Xvmsg(va_tail)
Xva_tdcl
X{
X    static char errmsg[512] = "";
X    char *fmt;
X    
X    fmt = va_arg1(char *);
X    
X    if (fmt) vsprintf(errmsg, fmt, va_args2toN);
X
X    gotoxy(0, Lines-1);
X    fputs(errmsg, stdout);
X    clrline();
X    any_message = 1;
X    
X    gotoxy(prompt_length, prompt_line);
X    fl;
X}
X
Xclrmsg(col)
Xint col;
X{
X    gotoxy(0, prompt_line + 1);
X    clrpage(prompt_line + 1);
X    if (col >= 0)
X	gotoxy(prompt_length + col, prompt_line);
X    fl;
X    any_message = 0;
X}
X
X
X/*VARARGS*/
Xprompt(va_alist)
Xva_dcl
X{
X    register char *cp;
X    int stand_on;
X    char *fmt;
X    static char cur_p[FILENAME];
X    va_list ap;
X    
X    va_start(ap);
X    
X    fmt = va_arg1(char *);
X
X    if (fmt == P_VERSION) {
X	gotoxy(0, prompt_line + 1);
X	print_version("Release %R.%V, Patch Level %P, Compilation %U ");
X	clrline();
X	any_message++;
X	
X	if (prompt_line >= 0)
X	    gotoxy(prompt_length, prompt_line);
X	return;
X    }
X    
X    if (prompt_line >= 0)
X	gotoxy(0, prompt_line);
X
X    if (fmt == P_MOVE) {
X	clrline();
X	return;
X    }
X
X    if (fmt != P_REDRAW) 
X	vsprintf(cur_p, fmt, va_args2toN);
X
X    putchar('\r');
X    
X    for (cp = cur_p, stand_on = 0, prompt_length = 0; *cp; cp++) {
X	if (*cp == '\1') {
X	    if (cp[1] != '\1') {
X		if (STANDOUT) {
X		    putp(stand_on ? exit_standout_mode : enter_standout_mode);
X		    stand_on = !stand_on;
X		    prompt_length += cookie_size;
X		}
X		continue;
X	    }
X	    cp++;
X	} else
X	if (*cp == '\2') {
X	    time_t t;
X	    char   *timestr;
X	    
X#ifdef STATISTICS
X	    tick_usage(&t, (time_t *)NULL);
X#endif	    
X
X	    if (show_current_time) {
X#ifndef STATISTICS	    
X		time(&t);
X#endif
X
X		timestr = ctime(&t) + 11;
X		timestr[5] = NUL;
X
X		printf("-- %s ", timestr);
X		prompt_length += 9;
X	    }
X
X	    if (unread_mail(t)) {
X		printf("Mail ");
X		prompt_length += 5;
X	    }
X	    
X	    continue;
X	}
X
X	putchar(*cp);
X	prompt_length ++;
X    }
X    if (stand_on) {
X	putp(exit_standout_mode);
X	prompt_length += cookie_size;
X    }
X    
X    clrline();
X}
X
X
Xany_key(line)
Xint line;
X{
X    int was_raw, c, dmp;
X
X    was_raw = is_raw;
X    if (!is_raw) raw();
X    if (line == 0)
X	line = -1;
X    else
X	if (line < 0)
X	    line = Lines + line;
X    
X    if (line != 10000)
X	so_printxy(0, line, "Hit any key to continue");
X
X    clrline();
X    
X    dmp = do_macro_processing;
X    do_macro_processing = 0;
X    c = get_c();
X    do_macro_processing = dmp;
X
X    if (!was_raw) no_raw();
X    
X    return c;
X}
X
X
Xstatic pg_fline, pg_width, pg_maxw, pg_line, pg_col, pg_quit;
X
Xpg_init(first_line, cols)
Xint first_line, cols;
X{
X    pg_fline = first_line;
X    pg_line = pg_fline - 1;
X    pg_quit = pg_col = 0;
X    pg_width = Columns / cols;
X    pg_maxw = pg_width * (cols - 1);
X}
X
Xpg_next()
X{
X    int c;
X    
X    pg_line++;
X    if (pg_line < Lines) {
X	gotoxy(pg_col, pg_line);
X	if (pg_line == Lines - 1 && pg_col == pg_maxw) {
X	    c = any_key(0);
X	    gotoxy(0, pg_fline);
X	    clrpage(pg_fline);
X	    pg_col = 0;
X	    pg_line = pg_fline;
X	    if (c == K_interrupt) {
X		pg_quit = 1;
X		return -1;
X	    }
X	    return 1;
X	}
X    } else {
X	pg_line = pg_fline;
X	pg_col += pg_width;
X	gotoxy(pg_col, pg_line);
X    }
X    return 0;
X}
X
Xpg_indent(pos)
Xint pos;
X{
X    gotoxy(pg_col + pos, pg_line);
X}
X
Xpg_end()
X{
X    if (pg_quit == 0 && pg_next() == 0)
X	any_key(0);
X}
X
X	
Xuser_delay(ticks)
Xint ticks;
X{
X    if (ticks <= 0 || conf_dont_sleep) {
X	printf(" <>");
X	any_key(10000);
X    } else {
X	fl;
X	sleep(ticks);
X    }
X}
X
NO_NEWS_IS_GOOD_NEWS
echo "File term.c is complete"
chmod 0644 term.c || echo "restore of term.c fails"
set `wc -c term.c`;Sum=$1
if test "$Sum" != "23957"
then echo original size 23957, current size $Sum;fi
echo "x - extracting term.h (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > term.h &&
X/*
X * terminal interface
X */
X 
X
X
Xextern init_term();
Xextern home();
Xextern gotoxy();
Xextern clrdisp(), clrpage();
Xextern clrline();
X
Xextern so_gotoxy(), so_printf(), so_end();
X
Xextern int Lines, Columns;
Xextern int cookie_size;
Xextern int WRAP, STANDOUT;
X
Xextern char *get_s();
X
X#define	NONE		(char *)NULL /* no default string etc. */
X
X#define	NO_COMPLETION	((int (*)()) 0)
X#define	GET_S_BUFFER	256 	/* if caller want to reuse get_s buffer */
X
Xextern get_c();
X
X/*
X *	prompt_line = ...
X *	prompt( [P_COMMAND], ] [ format [, arg1 ... , arg4] ] );
X *
X *	P_MOVE:		just move to prompt line
X *	P_REDRAW:	redraw prompt
X *      P_VERSION:	print version on prompt line
X */
X
X
Xextern prompt();
X
Xint prompt_line;	/* prompt line */
X
X#define	P_MOVE		(char *)1
X#define P_REDRAW	(char *)5
X#define	P_VERSION	(char *)9
X
X
Xextern display_file();
X
X#define	CLEAR_DISPLAY	0x01
X#define	CONFIRMATION	0x02
NO_NEWS_IS_GOOD_NEWS
chmod 0644 term.h || echo "restore of term.h fails"
set `wc -c term.h`;Sum=$1
if test "$Sum" != "880"
then echo original size 880, current size $Sum;fi
echo "x - extracting unshar.c (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > unshar.c &&
X/****************************************************************
X * unshar.c: Unpackage one or more shell archive files
X *
X * Description:	unshar is a filter which removes the front part
X *		of a file and passes the rest to the 'sh' command.
X *		It understands phrases like "cut here", and also
X *		knows about shell comment characters and the Unix
X *		commands "echo", "cat", and "sed".
X *
X * HISTORY
X *  27-July-88  Kim F. Storm (storm@texas.dk) Texas Instruments, Denmark
X *	Adapted to :unshar command in nn
X *	Added static to function declarations
X *	Removed all unused functions, i.e. not useful as stand-alone pgm.
X * 29-Jan-85  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X ****************************************************************/
X
X#include "config.h"
X
X
X/****************************************************************
X * position: position 'fil' at the start of the shell command
X * portion of a shell archive file.
X * Kim Storm: removed static variables
X ****************************************************************/
X
Xunshar_position (fil)
XFILE *fil;
X{
X    char buf[BUFSIZ];
X    long pos, ftell ();
X    
X    /* Results from star matcher */
X    char res1[BUFSIZ], res2[BUFSIZ], res3[BUFSIZ], res4[BUFSIZ];
X    char *result[4];
X    
X    result[0] = res1, result[1] = res2, result[2] = res3, result[3] = res4 ;
X    
X    /*  rewind (fil);  */
X    
X    while (1) {
X	/* Record position of the start of this line */
X	pos = ftell (fil);
X	
X	/* Read next line, fail if no more */
X	if (fgets (buf, BUFSIZ, fil) == NULL) {
X	    msg("no shell commands in file");
X	    return (0);
X	}
X	
X	/* Bail out if we see C preprocessor commands or C comments */
X	if (stlmatch (buf, "#include")	|| stlmatch (buf, "# include") ||
X	    stlmatch (buf, "#define")	|| stlmatch (buf, "# define") ||
X	    stlmatch (buf, "#ifdef")	|| stlmatch (buf, "# ifdef") ||
X	    stlmatch (buf, "#ifndef")	|| stlmatch (buf, "# ifndef") ||
X	    stlmatch (buf, "/*"))
X	    {
X		msg("file looks like raw C code, not a shar file");
X		return (0);
X	    }
X	
X	/* Does this line start with a shell command or comment */
X	if (stlmatch (buf, "#")	|| 
X	    stlmatch (buf, ":") ||
X	    stlmatch (buf, "echo ") ||
X	    stlmatch (buf, "sed ") ||
X	    stlmatch (buf, "cat ")) 
X	{ 
X	    fseek (fil, pos, 0);
X	    return (1); 
X	}
X	
X	/* Does this line say "Cut here" */
X	if (smatch (buf, "*CUT*HERE*", result) ||
X	    smatch (buf, "*cut*here*", result) ||
X	    smatch (buf, "*TEAR*HERE*", result) ||
X	    smatch (buf, "*tear*here*", result) ||
X	    smatch (buf, "*CUT*CUT*", result) ||
X	    smatch (buf, "*cut*cut*", result))
X	{
X		/* Read next line after "cut here", skipping blank lines */
X	    while (1) {
X		pos = ftell (fil);
X		
X		if (fgets (buf, BUFSIZ, fil) == NULL) { 
X		    msg("no shell commands after 'cut'");
X		    return (0);
X		}
X		
X		if (*buf != '\n') break;
X	    }
X	    
X	    /* 
X	     * Win if line starts with a comment character of 
X	     * lower case letter 
X	     */
X	    if (*buf == '#' ||
X		*buf == ':' ||
X		(('a' <= *buf) && ('z' >= *buf))) {
X		fseek (fil, pos, 0);
X		return (1);
X	    }
X	    
X	    /* Cut here message lied to us */      
X	    msg("invalid data after CUT line");
X	    return (0);
X	}
X    }
X}
X
X/*****************************************************************
X * stlmatch  --  match leftmost part of string
X *
X * Usage:  i = stlmatch (big,small)
X *	int i;
X *	char *small, *big;
X *
X * Returns 1 iff initial characters of big match small exactly;
X * else 0.
X *
X * HISTORY
X * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University
X *      Ripped out of CMU lib for Rog-O-Matic portability
X * 20-Nov-79  Steven Shafer (sas) at Carnegie-Mellon University
X *	Rewritten for VAX from Ken Greer's routine.
X *
X *  Originally from klg (Ken Greer) on IUS/SUS UNIX
X *****************************************************************/
X
Xstatic int   stlmatch (big, small)
Xchar *small, *big;
X{ register char *s, *b;
X  s = small;
X  b = big;
X  do
X  { if (*s == '\0')
X      return (1);
X  }
X  while (*s++ == *b++);
X  return (0);
X}
X
X/*****************************************************************
X * smatch: Given a data string and a pattern containing one or
X * more embedded stars (*) (which match any number of characters)
X * return true if the match succeeds, and set res[i] to the
X * characters matched by the 'i'th *.
X *****************************************************************/
X
Xstatic smatch (dat, pat, res)
Xregister char *dat, *pat, **res;
X{ register char *star = 0, *starend, *resp;
X  int nres = 0;
X
X  while (1)
X  { if (*pat == '*')
X    { star = ++pat; 			     /* Pattern after * */
X      starend = dat; 			     /* Data after * match */
X      resp = res[nres++]; 		     /* Result string */
X      *resp = '\0'; 			     /* Initially null */
X    }
X    else if (*dat == *pat) 		     /* Characters match */
X    { if (*pat == '\0') 		     /* Pattern matches */
X	return (1);
X      pat++; 				     /* Try next position */
X      dat++;
X    }
X    else
X    { if (*dat == '\0') 		     /* Pattern fails - no more */
X	return (0); 			     /* data */
X      if (star == 0) 			     /* Pattern fails - no * to */
X	return (0); 			     /* adjust */
X      pat = star; 			     /* Restart pattern after * */
X      *resp++ = *starend; 		     /* Copy character to result */
X      *resp = '\0'; 			     /* null terminate */
X      dat = ++starend; 			     /* Rescan after copied char */
X    }
X  }
X}
NO_NEWS_IS_GOOD_NEWS
chmod 0644 unshar.c || echo "restore of unshar.c fails"
set `wc -c unshar.c`;Sum=$1
if test "$Sum" != "5388"
then echo original size 5388, current size $Sum;fi
echo "x - extracting update.c (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > update.c &&
X#include "patchlevel.h"
X#include "update.h"
X
Xint Update_Level = UPDATE;
Xint Patch_Level = PATCHLEVEL;
X
X
NO_NEWS_IS_GOOD_NEWS
chmod 0644 update.c || echo "restore of update.c fails"
set `wc -c update.c`;Sum=$1
if test "$Sum" != "104"
then echo original size 104, current size $Sum;fi
echo "x - extracting update.h (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > update.h &&
X#define UPDATE 0
NO_NEWS_IS_GOOD_NEWS
chmod 0644 update.h || echo "restore of update.h fails"
set `wc -c update.h`;Sum=$1
if test "$Sum" != "17"
then echo original size 17, current size $Sum;fi
echo "x - extracting vararg.h (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > vararg.h &&
X
X/*
X * semi-faked varargs feature
X */
X
X#ifdef NO_VARARGS
X
X#define va_alist	a, b, c, d, e, f, g, h
X#define va_dcl		char *a, *b, *c, *d, *e, *f, *g, *h;
X#define va_list		int
X
X#define va_arg1(type)	(type)a
X#define va_arg2(type)	(type)b
X#define va_args1toN	a, b, c, d, e, f, g, h
X#define va_args2toN	b, c, d, e, f, g, h
X#define va_args3toN	c, d, e, f, g, h
X
X#define vsprintf	sprintf
X#define vprintf		printf
X
X#define va_start(ap)
X#define va_end(ap)
X
X#define va_tail		va_alist
X#define va_tdcl		va_dcl
X
X#else
X
X#include <varargs.h>
X
X#define va_tail		ap
X#define	va_tdcl		va_list va_tail;
X
X#define va_arg1(type)	va_arg(ap, type)
X#define va_arg2(type)	va_arg(ap, type)
X#define va_args1toN	ap
X#define va_args2toN	ap
X#define va_args3toN	ap
X
X#endif
X
X
NO_NEWS_IS_GOOD_NEWS
chmod 0644 vararg.h || echo "restore of vararg.h fails"
set `wc -c vararg.h`;Sum=$1
if test "$Sum" != "737"
then echo original size 737, current size $Sum;fi
echo "x - extracting variable.c (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > variable.c &&
X/*
X *	Variabel setting and display
X */
X
X#include "config.h"
X
Ximport in_init;
X
Ximport char			/* string variables */
X    *default_save_file,
X    *header_lines,
X    *folder_directory,
X    included_mark[],
X    *mail_box,
X    *mail_record,
X    *news_record,
X#ifdef NNTP
X    nntp_server[],
X#endif
X    *pager,
X    *patch_cmd,
X    printer[],
X    *save_counter_format;
X
Ximport int			/* boolean variables */
X    conf_append,
X    conf_dont_sleep,
X    delay_redraw,
X    do_kill_handling,
X    dont_sort_articles,
X    dont_sort_folders,
X    dont_split_digests,
X    fmt_rptsubj,
X    keep_rc_backup,
X    long_menu,
X    macro_debug,
X    mark_overlap,
X    monitor_mode,
X    novice,
X    quick_save,
X    save_report,
X    show_article_date,
X    show_current_time,
X    silent,
X    use_mail_folders,
X    use_newsrc;
X
Ximport int			/* integer variables */
X    also_read_articles,
X    article_limit,
X    Debug,
X    first_page_lines,
X    fmt_linenum,
X    Lines,
X    overlap,
X    preview_window,
X    retry_on_error;
X
Ximport char			/* key strokes */
X    comp1_key,
X    comp2_key,
X    help_key,
X    erase_key,
X    delword_key,
X    kill_key;
X
X#define	V_STRING	0
X#define V_BOOLEAN	1
X#define	V_INTEGER	2
X#define V_KEY		3
X#define	V_SPECIAL	4
X
Xstruct variable_defs {
X    char *var_name;
X    char var_type;
X    char var_op;
X    char **var_addr;
X} variables[] = {
X    "backup",		V_BOOLEAN,	3,	(char **)&keep_rc_backup,
X    "comp1_key",	V_KEY,		0,	(char **)&comp1_key,
X    "comp2_key",	V_KEY,		0,	(char **)&comp2_key,
X    "confirm",		V_BOOLEAN,	0,	(char **)&conf_dont_sleep,
X    "confirm-append",	V_BOOLEAN,	0,	(char **)&conf_append,
X    "date",		V_BOOLEAN,	0,	(char **)&show_article_date,
X    "debug",		V_INTEGER,	0,	(char **)&Debug,
X    "default-save-file",V_STRING,	0,	(char **)&default_save_file,
X    "delay-redraw",	V_BOOLEAN,	0,	(char **)&delay_redraw,
X    "erase-key",	V_KEY,		0,	(char **)&erase_key,
X    "expert",		V_BOOLEAN,	4,	(char **)&novice,
X    "folder",		V_STRING,	2,	(char **)&folder_directory,
X    "fsort",		V_BOOLEAN,	2,	(char **)&dont_sort_folders,
X    "header-lines",	V_STRING,	0,	(char **)&header_lines,
X    "help-key",		V_KEY,		0,	(char **)&help_key,
X    "included-mark",	V_STRING,	1,	(char **)included_mark,
X    "kill",		V_BOOLEAN,	0,	(char **)&do_kill_handling,
X    "kill-key",		V_KEY,		0,	(char **)&kill_key,
X    "layout",		V_INTEGER,	1,	(char **)&fmt_linenum,
X    "limit",		V_INTEGER,	0,	(char **)&article_limit,
X    "lines",		V_INTEGER,	1,	(char **)&Lines,
X    "long-menu",	V_BOOLEAN,	1,	(char **)&long_menu,
X    "macro-debug",	V_BOOLEAN,	0,	(char **)&macro_debug,
X    "mail",		V_STRING,	0,	(char **)&mail_box,
X    "mail-format",	V_BOOLEAN,	0,	(char **)&use_mail_folders,
X    "mail-record",	V_STRING,	2,	(char **)&mail_record,
X    "mark-overlap",	V_BOOLEAN,	0,	(char **)&mark_overlap,
X    "monitor",		V_BOOLEAN,	0,	(char **)&monitor_mode,
X    "news-record",	V_STRING,	2,	(char **)&news_record,
X    "newsrc",		V_BOOLEAN,	0,	(char **)&use_newsrc,
X#ifdef NNTP
X    "nntp-server",	V_STRING,	1,	(char **)nntp_server,
X#endif
X    "old",		V_SPECIAL,	2,	(char **)NULL,
X    "overlap",		V_INTEGER,	0,	(char **)&overlap,
X    "pager",		V_STRING,	0,	(char **)&pager,
X    "patch-cmd",	V_STRING,	0,	(char **)&patch_cmd,
X    "printer",		V_STRING,	1,	(char **)printer,
X    "quick-save",	V_BOOLEAN,	0,	(char **)&quick_save,
X    "record",		V_SPECIAL,	1,	(char **)NULL,
X    "repeat",		V_BOOLEAN,	0,	(char **)&fmt_rptsubj,
X    "retry-on-error",	V_INTEGER,	0,	(char **)&retry_on_error,
X    "save-counter",	V_STRING,	0,	(char **)&save_counter_format,
X    "save-report",	V_BOOLEAN,	0,	(char **)&save_report,
X    "silent",		V_BOOLEAN,	0,	(char **)&silent,
X    "sort",		V_BOOLEAN,	2,	(char **)&dont_sort_articles,
X    "split",		V_BOOLEAN,	4,	(char **)&dont_split_digests,
X    "stop",		V_INTEGER,	0,	(char **)&first_page_lines,
X    "time",		V_BOOLEAN,	0,	(char **)&show_current_time,
X    "window",		V_INTEGER,	1,	(char **)&preview_window,
X    "word-key",		V_KEY,		0,	(char **)&delword_key
X};
X
X#define TABLE_SIZE	(sizeof(variables)/sizeof(struct variable_defs))
X
X#define INT_VAR		(*((int *)(var->var_addr)))
X#define BOOL_VAR	(*((int *)(var->var_addr)))
X#define STR_VAR		(*(var->var_addr))
X#define CBUF_VAR	((char *)(var->var_addr))
X#define KEY_VAR		(*((char *)(var->var_addr)))
X
X
Xstatic struct variable_defs *lookup_variable(variable)
Xchar *variable;
X{
X    register struct variable_defs *var;
X    register i, j, k, t;
X    
X    i = 0; j = TABLE_SIZE - 1; 
X    
X    while (i <= j) {
X	k = (i + j) / 2;
X	var = &variables[k];
X	
X	if ( (t=strcmp(variable, var->var_name)) > 0) 
X	    i = k+1;
X	else
X	if (t < 0)
X	    j = k-1;
X	else
X	    return var;
X    }
X
X    init_message("unknown variable: %s", variable);
X    return NULL;
X}    
X
X
Xset_variable(variable, on, val_string)
Xchar *variable;
Xint on;
Xchar *val_string;
X{
X    long value;
X    register struct variable_defs *var;
X
X    if (strncmp(variable, "no", 2) == 0) {
X	on = !on;
X	variable += 2;
X    }
X    
X    if ((var = lookup_variable(variable)) == NULL) 
X	return 0;
X    
X    if (!on || val_string == NULL)
X	value = 0;
X    else	
X	value = atol(val_string);
X
X    switch (var->var_type) {
X	
X     case V_STRING:
X
X	switch (var->var_op) {
X	 case 0:
X	    if (val_string) STR_VAR = copy_str(val_string);
X	    break;
X
X	 case 1:
X	    if (val_string) strcpy(CBUF_VAR, val_string);
X	    break;
X
X	 case 2:
X	    adjust(val_string);
X	    if (val_string) STR_VAR = home_relative(val_string);
X	    break;
X	}
X	break;
X	
X     case V_BOOLEAN:
X	
X	switch (var->var_op) {
X	 case 0:
X	    BOOL_VAR = on;
X	    break;
X	    
X	 case 1:
X	    BOOL_VAR = on;
X	    return 1;
X	    
X	 case 2:
X	    if (BOOL_VAR == on) {
X		BOOL_VAR = !on;
X		if (!in_init) {
X		    if (BOOL_VAR)
X			unsort_articles(1);
X		    else
X			sort_articles();
X		    return 1;
X		}
X	    }	
X	    break;
X	    
X	 case 3:
X	    if (!in_init) {
X		msg("'%s' can only be set in the init file", variable);
X		break;
X	    }
X	    BOOL_VAR = on;
X	    break;	    
X
X	 case 4:
X	    BOOL_VAR = !on;
X	    break;
X	}
X	break;
X
X     case V_INTEGER:
X
X	switch (var->var_op) {
X	 case 0:
X	    INT_VAR = value;	    
X	    break;
X	    
X	 case 1:
X	    INT_VAR = value; 
X	    return 1;
X	}
X	break;
X	
X     case V_KEY:
X	switch (var->var_op) {
X	 case 0:
X	    if (val_string) {
X		if (*val_string) adjust(val_string + 1); /* #N is valid */
X		KEY_VAR = parse_key(val_string);
X	    }
X	    break;
X	}
X	break;
X	
X     case V_SPECIAL:
X	
X	switch (var->var_op) {
X	 case 1:
X	    if (val_string) {
X		adjust(val_string);
X		news_record = home_relative(val_string);
X		mail_record = news_record;
X	    }
X	    break;
X	    
X	 case 2:
X	    also_read_articles = on;
X	    article_limit = value;
X	    break;
X	}	    
X	break;
X    }
X    return 0;
X}
X    
Xstatic adjust(str)
Xregister char *str;
X{
X    if (str == NULL) return;
X    while (*str && !isspace(*str) && *str != '#') str++;
X    *str = NUL;
X}
X
X
Xdisp_variables()
X{
X    char *str, *key_name();
X    int i, b;
X    register struct variable_defs *var;
X    
X    if (in_init) return;
X
X    pg_init(0, 1);
X    
X    clrdisp();
X    pg_next();
X    so_printf("\1Variable settings:\1");
X
X    for (var = variables; var < &variables[TABLE_SIZE]; var++) {
X	switch (var->var_type) {
X	 case V_STRING:
X	    str = (var->var_op == 1) ? CBUF_VAR : STR_VAR;
X	    if (str == NULL || *str == NUL) break;
X	    
X	    if (pg_next() < 0) goto out;
X	    printf("%-20.20s = \"%s\"\n", var->var_name, str);
X	    break;
X
X	 case V_BOOLEAN:
X	    if (pg_next() < 0) goto out;
X	    b = BOOL_VAR;
X	    if (var->var_op == 2 || var->var_op == 4) b = !b;
X	    printf("%s%s\n", b ? "" : "no", var->var_name);
X	    break;
X	    
X	 case V_INTEGER:
X	    i = INT_VAR;
X	    if (i == 0) break;
X	    if (pg_next() < 0) goto out;
X	    printf("%-20.20s = %d\n", var->var_name, i);
X	    break;
X	    
X	 case V_KEY:
X	    if (pg_next() < 0) goto out;
X	    printf("%-20.20s = %s\n", var->var_name, key_name(KEY_VAR));
X	    break;
X	    
X	 case V_SPECIAL:
X	    switch (var->var_op) {
X	     case 1:
X		break;
X	     case 2:
X		if (also_read_articles) {
X		    if (pg_next() < 0) goto out;
X		    printf("%-20.20s = %d\n", var->var_name, article_limit);
X		}
X		break;
X	    }
X	    break;
X	}
X    }
X    
Xout:
X    pg_end();
X}
X
Xtoggle_variable(variable)
Xchar *variable;
X{
X    register struct variable_defs *var;
X    
X    if ((var = lookup_variable(variable)) == NULL) return;
X    if (var->var_type != V_BOOLEAN) {
X	init_message("variable %s is not boolean", variable);
X	return;
X    }
X    
X    BOOL_VAR = !BOOL_VAR;
X}
X
X
Xtest_variable(expr)
Xchar *expr;
X{
X    char *variable;
X    register struct variable_defs *var;
X    int res = -1;
X    
X    variable = expr;
X    if ((expr = strchr(variable, '=')) == NULL) 
X	goto err;
X    
X    *expr++ = NUL;
X    
X    if ((var = lookup_variable(variable)) == NULL) {
X	msg("testing unknown variable %s=%s", variable, expr);
X	goto out;
X    }    
X
X    switch (var->var_type) {
X	
X     case V_BOOLEAN:
X	res = BOOL_VAR;
X	
X	if (strcmp(expr, "on") == 0) break;
X	if (strcmp(expr, "off") == 0) {
X	    res = !res;
X	    break;
X	}
X	msg("boolean variables must be tested =on or =off");
X	break;
X	
X     case V_INTEGER:
X	res = (INT_VAR == atoi(expr)) ? 1 : 0;
X	break;
X	
X     default:
X	msg("%s: cannot only test boolean and integer variables", variable);
X	break;
X    }
X out:
X    *--expr = '=';
X err:
X    return res;
X}
X
X
Xvar_completion(path, index)
Xchar *path;
Xint index;
X{
X    static char *head, *tail = NULL;
X    static int len;
X    static struct variable_defs *var, *help_var;
X
X    if (index < 0) return 0;
X
X    if (path) {
X	head = path;
X	tail = path + index;
X	while (*head && isspace(*head)) head++;
X	help_var = var = variables;
X	len = tail - head;
X	
X	return 1;
X    }
X    
X    if (index) {
X	list_completion((char *)NULL);
X	
X	for (;; help_var++) {
X	    if (help_var >= &variables[TABLE_SIZE]) {
X		help_var = variables;
X		break;
X	    }
X	    
X	    index = strncmp(help_var->var_name, head, len);
X	    if (index < 0) continue;
X	    if (index > 0) {
X		help_var = variables;
X		break;
X	    }
X	    if (list_completion(help_var->var_name) == 0) break;
X	}
X	fl;
X	return 1;
X    }
X
X    for (; var < &variables[TABLE_SIZE]; var++) {
X	if (len == 0) 
X	    index = 0;
X	else
X	    index = strncmp(var->var_name, head, len);
X	if (index < 0) continue;
X	if (index > 0) break;
X	sprintf(tail, "%s ", var->var_name + len);
X	var++;
X	return 1;
X    }
X    return 0;
X}
X
NO_NEWS_IS_GOOD_NEWS
chmod 0644 variable.c || echo "restore of variable.c fails"
set `wc -c variable.c`;Sum=$1
if test "$Sum" != "10209"
then echo original size 10209, current size $Sum;fi
echo "x - extracting xmakefile (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > xmakefile &&
X*
X* DO NOT CHANGE THIS MAKEFILE DIRECTLY
X*
X* THERE ARE NO CONFIGURATION PARAMETERS IN THIS FILE
X*
X
X#include "config.h"
X#undef global
X#undef SHELL
X
X#ifndef COMPILER_FLAGS
X#define COMPILER_FLAGS
X#endif
X
X#ifndef EXTRA_LIB
X#define EXTRA_LIB
X#endif
X
X#ifdef HAVE_ROUTING
X#define NNMAIL
X#else
X#define	NNMAIL nnmail
X#endif
X
X------------------ MAKE WILL CUT HERE -------------
X*
X* Notice:  ymakefile is made from xmakefile by the Makefile.
X*
X
XCC =	 COMPILER
XCPP =	 PREPROC
XCFLAGS = COMPILER_FLAGS CDEBUG
X
X*
X* Resulting programs
X*
X
XBIN_PROG =	nn NNMAIL nntidy nngrep nnquery nnusage nngoback
XBIN_LINK =	nncheck nnadmin
XLIB_PROG =	aux date_regexp log_entry back_act
XMASTER_PROG =	nnmaster
X
X*
X* Compilation
X*
X
XSHELL = /bin/sh
X
XMASTER = master.o collect.o expire.o update.o \
X	global.o options.o active.o db.o nntp.o \
X	pack_date.o pack_name.o pack_subject.o news.o digest.o match.o 
X
XNN = 	nn.o admin.o update.o \
X	global.o options.o active.o db.o nntp.o \
X	init.o variable.o term.o keymap.o macro.o regexp.o \
X	menu.o more.o rc.o group.o folder.o \
X	articles.o sequence.o selection.o kill.o \
X	answer.o reroute.o save.o unshar.o execute.o \
X	pack_date.o pack_name.o pack_subject.o news.o digest.o match.o 
X
XMAIL = nnmail.o reroute.o global.o options.o update.o
X
X
Xall:	$(BIN_PROG) $(LIB_PROG) $(MASTER_PROG)
X
Xclient: update.o $(BIN_PROG) $(LIB_PROG)
X
X
Xnn:	$(NN) 
X	$(CC) $(CFLAGS) $(NN) TERMLIB EXTRA_LIB -o nn
X
Xnnmaster: $(MASTER)
X	$(CC) $(CFLAGS) $(MASTER) EXTRA_LIB -o nnmaster
X
Xnnmail:	$(MAIL)
X	$(CC) $(CFLAGS) $(MAIL) EXTRA_LIB -o nnmail
X
Xnntidy:	nntidy.sh prefix
X	cat prefix nntidy.sh > nntidy
X	chmod +x nntidy
X
Xnngrep:	nngrep.sh prefix
X	cat prefix nngrep.sh > nngrep
X	chmod +x nngrep
X
Xnngoback: nngoback.sh prefix
X	cat prefix nngoback.sh > nngoback
X	chmod +x nngoback
X
Xnnquery: nnquery.sh prefix
X	cat prefix nnquery.sh > nnquery
X	chmod +x nnquery
X
Xnnusage: nnusage.sh prefix
X	cat prefix nnusage.sh > nnusage
X	chmod +x nnusage
X
X* LIB PROGRAMS
X
Xdate_regexp: date_regexp.o
X	$(CC) $(CFLAGS) date_regexp.o EXTRA_LIB -o date_regexp
X
Xlog_entry: log_entry.o global.o update.o
X	$(CC) $(CFLAGS) log_entry.o global.o update.o EXTRA_LIB -o log_entry
X
Xaux:	 aux.sh prefix
X	cat prefix aux.sh > aux
X	chmod +x aux
X
Xback_act: back_act.sh prefix
X	cat prefix back_act.sh > back_act
X	chmod +x back_act
X
X
X*
X* Clean -- remove compiled programs
X*
X
Xclean:
X	rm -f $(BIN_PROG) $(LIB_PROG) $(MASTER_PROG) cvt-help
X
X*
X* Compilation counter updating
X*
X
Xupdate.o:	update.h update.c
X	-$(CC) -c $(CFLAGS) update.c
X
X*
X* Installation
X*
X
Xinstall: prefix install.bin install.lib install.master install.man
X	@sh install_aux incr OWNER GROUP LIB_DIRECTORY "Log" 666 \
X		"Installation" DB_DIRECTORY
X
Xinstall.client: prefix install.bin install.lib install.man
X	@sh install_aux incr OWNER GROUP LIB_DIRECTORY "Log" 666 \
X		"Client Installation"
X
Xinstall.bin: $(BIN_PROG)
X	@sh install_aux bin OWNER GROUP BIN_DIRECTORY "$(BIN_PROG)" 755 \
X		"$(BIN_LINK)"
X
Xinstall.lib: $(LIB_PROG) cvt-help
X	@sh install_aux aux  OWNER GROUP LIB_DIRECTORY "$(LIB_PROG)" 755
X	@sh install_aux help OWNER GROUP LIB_DIRECTORY "help.*" 644
X
Xinstall.master: $(MASTER_PROG)
X	@sh install_aux master OWNER GROUP LIB_DIRECTORY "$(MASTER_PROG)" 6755
X
Xinstall.man: 
X	@sh install_aux 1  OWNER GROUP USER_MAN_DIR USER_MAN_SECTION 644
X	@sh install_aux 1m OWNER GROUP SYS_MAN_DIR  SYS_MAN_SECTION  644
X
Xonline.manual:
X	@sh install_aux online OWNER GROUP LIB_DIRECTORY "n*.1 n*.1m" 444
X
X*
X* initialize database
X*
X
Xinitdb:
X	@sh install_aux db OWNER GROUP DB_DIRECTORY ". DATA" 755
X	@sh install_aux init . . LIB_DIRECTORY "$(MASTER_PROG)" . "-I"
X
X
X*
X* dependencies
X*
X
Xprefix:	prefix.sh config.h update.h patchlevel.h ymakefile
X	cp prefix.sh prefix.c
X	$(CPP) prefix.c | \
X	sed -e '1,/CUT PREFIX HERE/d' \
X	    -e '/prefix.c/d' \
X	    -e '/^[ 	]*$$/d' \
X	    -e 's/^&/#/' \
X	    -e 's/[ 	]*=[ 	]*/=/' > prefix
X	rm -f prefix.c
X
Xcvt-help:	cvt-help.c
X	cc -o cvt-help cvt-help.c
X
Xactive.o:	active.c config.h global.h data.h
X
Xadmin.o:	admin.c config.h global.h data.h term.h db.h
X
Xanswer.o:	answer.c config.h global.h data.h news.h term.h keymap.h
X
Xarticles.o:	articles.c config.h global.h data.h articles.h db.h match.h
X
Xcollect.o:	collect.c config.h global.h data.h db.h news.h
X
Xdate_regexp.o:	config.h global.h data.h
X
Xdb.o:		db.c config.h global.h data.h db.h
X
Xdigest.o:	digest.c config.h global.h data.h news.h match.h
X
Xexecute.o:	execute.c config.h global.h data.h term.h
X
Xexpire.o:	expire.c config.h global.h data.h
X
Xfolder.o:	folder.c config.h global.h data.h articles.h news.h term.h menu.h
X
Xglobal.o:	global.c config.h global.h data.h
X
Xgroup.o:	group.c config.h global.h data.h articles.h db.c term.h menu.h keymap.h
X
Xinit.o:		init.c config.h global.h data.h articles.h keymap.h term.h menu.h 
X
Xkeymap.o:	keymap.c config.h global.h data.h keymap.h term.h
X
Xkill.o:		kill.c config.h global.h data.h term.h
X
Xlog_entry.o:	log_entry.c
X
Xmaster.o:	master.c config.h global.h data.h
X
Xmenu.o:		menu.c config.h global.h data.h articles.h term.h menu.h keymap.h
X
Xmore.o:		more.c config.h global.h data.h news.h term.h menu.h keymap.h
X
Xnews.o:		news.c config.h global.h data.h news.h
X
Xnn.o:		nn.c config.h global.h data.h menu.h term.h keymap.h
X
Xnnmail.o:	nnmail.c config.h global.h data.h options.h
X
Xnntp.o:		nntp.c config.h global.h data.h nntp.h
X
Xoptions.o:	options.c config.h global.h data.h options.h
X
Xpack_date.o:	pack_date.c config.h global.h data.h
X
Xpack_name.o:	pack_name.c config.h global.h data.h
X
Xpack_subject.o:	pack_subject.c config.h global.h data.h 
X
Xrc.o:		rc.c config.h global.h data.h term.h
X
Xreroute.o:	reroute.c config.h global.h data.h
X
Xsave.o:		save.c config.h global.h data.h term.h news.h keymap.h
X
Xselection.o:	selection.c config.h global.h data.h articles.h
X
Xsequence.o:	sequence.c config.h global.h data.h
X
Xvariable.o:	variable.c config.h global.h data.h 
X
Xterm.o:		term.c config.h global.h data.h term.h keymap.h
X
X* link debugging version
X
Xnn1:	$(NN) 
X	$(CC) $(CFLAGS) $(NN) TERMLIB EXTRA_LIB -Mnn1 -o nn1
X
X* this is probably non-portable so it is ifdef'ed
X
X#ifdef WITH_LINT
Xlint:
X	echo LINTING NN
X	lint $(NN:.o=.c)
X	echo LINTING MASTER
X	lint $(MASTER:.o=.c)
X#endif
NO_NEWS_IS_GOOD_NEWS
chmod 0644 xmakefile || echo "restore of xmakefile fails"
set `wc -c xmakefile`;Sum=$1
if test "$Sum" != "6101"
then echo original size 6101, current size $Sum;fi
rm -f s2_seq_.tmp
echo "You have unpacked the last part"
exit 0
---
Kim F. Storm        storm@texas.dk        Tel +45 429 174 00
Texas Instruments, Marielundvej 46E, DK-2730 Herlev, Denmark
	  No news is good news, but nn is better!

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.