[mod.sources] v09i016: ELM Mail System, Part16/19

sources-request@mirror.UUCP (03/12/87)

Submitted by: Dave Taylor <hplabs!taylor>
Mod.sources: Volume 9, Issue 16
Archive-name: elm2/Part16

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If this archive is complete, you will see the message:
#		"End of archive 16 (of 19)."
# Contents:  src/curses.c src/read_rc.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"src/curses.c\" \(16822 characters\)
if test -f src/curses.c ; then 
  echo shar: Will not over-write existing file \"src/curses.c\"
else
sed "s/^X//" >src/curses.c <<'END_OF_src/curses.c'
X/** 			curses.c		**/
X
X/**  This library gives programs the ability to easily access the
X     termcap information and write screen oriented and raw input
X     programs.  The routines can be called as needed, except that
X     to use the cursor / screen routines there must be a call to
X     InitScreen() first.  The 'Raw' input routine can be used
X     independently, however.
X
X     Modified 2/86 to work (hopefully) on Berkeley systems.  If
X     there are any problems with BSD Unix, please report them to
X     the author at taylor@hplabs (fixed, if possible!)
X
X     Modified 5/86 to add memory lock support, thanks to the
X     suggested code by Steve Wolf.
X
X     Modified (as if I'm keeping track) to add 24,80 defaults
X
X     (C) Copyright 1985 Dave Taylor, HP Colorado Networks
X**/
X
X#include "headers.h"
X
X#ifdef RAWMODE
X# ifdef BSD
X#  ifndef BSD4.1
X#    include <sgtty.h>
X#  else
X#    include <termio.h>
X#  endif
X# else
X#  include <termio.h>
X# endif
X#endif
X
X#include <ctype.h>
X
X#ifdef BSD
X#undef tolower
X#endif
X#include "curses.h"
X
X#ifdef RAWMODE
X# define TTYIN	0
X#endif
X
X#ifdef SHORTNAMES
X# define CleartoEOS	ClrtoEOS
X# define _clearinverse	_clrinv
X# define _cleartoeoln	_clrtoeoln
X# define _cleartoeos	_clr2eos
X# define _transmit_off	xmit_off
X# define _transmit_on	xmit_on
X#endif
X
Xextern int debug;
X
X#ifdef RAWMODE
X#  ifndef BSD
Xstruct termio _raw_tty, 
X              _original_tty;
X#  else
X#    define TCGETA	TIOCGETP
X#    define TCSETAW	TIOCSETP
X
Xstruct sgttyb _raw_tty,
X	      _original_tty;
X#  endif
X
Xstatic int _inraw = 0;                  /* are we IN rawmode?    */
X
X#endif
X
X#ifdef UTS
Xstatic int _clear_screen = 0;		/* Next i/o clear screen? */
Xstatic char _null_string[SLEN];		/* a string of nulls...   */
X#endif
X
X
X#define DEFAULT_LINES_ON_TERMINAL	24
X#define DEFAULT_COLUMNS_ON_TERMINAL	80
X
Xstatic int _memory_locked = 0;		/* are we IN memlock??   */
Xstatic int _line  = -1,			/* initialize to "trash" */
X           _col   = -1;
X
Xstatic int _intransmit;			/* are we transmitting keys? */
X
Xstatic
Xchar *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
X     *_setbold, *_clearbold, *_setunderline, *_clearunderline, 
X     *_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse,
X     *_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off,
X     *_set_memlock, *_clear_memlock;
X
Xstatic
Xint _lines, _columns;
X
Xstatic char _terminal[1024];              /* Storage for terminal entry */
Xstatic char _capabilities[1024];           /* String for cursor motion */
X
Xstatic char *ptr = _capabilities;	/* for buffering         */
X
Xint    outchar();			/* char output for tputs */
Xchar  *tgetstr(),     		       /* Get termcap capability */
X      *tgoto();				/* and the goto stuff    */
X
XInitScreen()
X{
X	/* Set up all this fun stuff: returns zero if all okay, or;
X        -1 indicating no terminal name associated with this shell,
X        -2..-n  No termcap for this terminal type known
X   */
X
X	int  tgetent(),      /* get termcap entry */
X	     error;
X	char termname[40];
X	char *strcpy(), *getenv();
X	
X	dprint0(8,"InitScreen()\n");
X
X	if (getenv("TERM") == NULL) return(-1);
X
X#ifdef UTS
X
X	/* use _line for lack of a better variable, what the heck! */
X
X	for (_line = 0; _line < SLEN; _line++)
X		_null_string[_line] = '\0';
X#endif
X
X	if (strcpy(termname, getenv("TERM")) == NULL)
X		return(-1);
X
X	if ((error = tgetent(_terminal, termname)) != 1)
X		return(error-2);
X
X	_line  =  0;		/* where are we right now?? */
X	_col   =  0;		/* assume zero, zero...     */
X
X	/* load in all those pesky values */
X	_clearscreen       = tgetstr("cl", &ptr);
X	_moveto            = tgetstr("cm", &ptr);
X	_up                = tgetstr("up", &ptr);
X	_down              = tgetstr("do", &ptr);
X	_right             = tgetstr("nd", &ptr);
X	_left              = tgetstr("bs", &ptr);
X	_setbold           = tgetstr("so", &ptr);
X	_clearbold         = tgetstr("se", &ptr);
X	_setunderline      = tgetstr("us", &ptr);
X	_clearunderline    = tgetstr("ue", &ptr);
X	_setinverse        = tgetstr("so", &ptr);
X	_clearinverse      = tgetstr("se", &ptr);
X	_sethalfbright     = tgetstr("hs", &ptr);
X	_clearhalfbright   = tgetstr("he", &ptr);
X	_cleartoeoln       = tgetstr("ce", &ptr);
X	_cleartoeos        = tgetstr("cd", &ptr);
X	_lines	      	   = tgetnum("li");
X	_columns	   = tgetnum("co");
X	_transmit_on	   = tgetstr("ks", &ptr);
X	_transmit_off      = tgetstr("ke", &ptr);
X	_set_memlock	   = tgetstr("ml", &ptr);
X	_clear_memlock	   = tgetstr("mu", &ptr);
X
X
X	if (!_left) {
X		_left = ptr;
X		*ptr++ = '\b';
X		*ptr++ = '\0';
X	}
X
X	return(0);
X}
X
Xchar *return_value_of(termcap_label)
Xchar *termcap_label;
X{
X	/** This will return the string kept by termcap for the 
X	    specified capability. Modified to ensure that if 
X	    tgetstr returns a pointer to a transient address	
X	    that we won't bomb out with a later segmentation
X	    fault (thanks to Dave@Infopro for this one!)
X
X	    Tweaked to remove padding sequences.
X	 **/
X
X	static char escape_sequence[20];
X	register int i=0,j=0;
X	char buffer[20];
X	char *myptr, *tgetstr();     		/* Get termcap capability */
X
X	dprint1(9,"return_value_of(%s)\n", termcap_label);
X
X	if (strlen(termcap_label) < 2)
X	  return(NULL);
X
X	if (termcap_label[0] == 's' && termcap_label[1] == 'o')
X	  strcpy(escape_sequence, _setinverse);
X	else if (termcap_label[0] == 's' && termcap_label[1] == 'e')
X	  strcpy(escape_sequence, _clearinverse);
X	else if ((myptr = tgetstr(termcap_label, &ptr)) == NULL)
X	  return( (char *) NULL );
X	else
X	  strcpy(escape_sequence, myptr);
X
X	if (chloc(escape_sequence, '$') != -1) {
X	  while (escape_sequence[i] != '\0') {
X	    while (escape_sequence[i] != '$' && escape_sequence[i] != '\0')
X	      buffer[j++] = escape_sequence[i++];
X	    if (escape_sequence[i] == '$') {
X	      while (escape_sequence[i] != '>') i++;
X	      i++;
X	    }
X	  }
X	  buffer[j] = '\0';
X	  strcpy(escape_sequence, buffer);
X	}
X
X	return( (char *) escape_sequence);
X}
X
Xtransmit_functions(newstate)
Xint newstate;
X{
X	/** turn function key transmission to ON | OFF **/
X
X	dprint1(9,"transmit_functions(%s)\n", onoff(newstate));
X
X	if (newstate != _intransmit) {
X		_intransmit = ! _intransmit;
X		if (newstate == ON)
X		  tputs(_transmit_on, 1, outchar);
X		else 
X		  tputs(_transmit_off, 1, outchar);
X		fflush(stdout);      /* clear the output buffer */
X	}
X}
X
X/****** now into the 'meat' of the routines...the cursor stuff ******/
X
XScreenSize(lines, columns)
Xint *lines, *columns;
X{
X	/** returns the number of lines and columns on the display. **/
X
X	if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
X	if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
X
X	dprint2(9,"ScreenSize(_,_) returning %d, %d\n", _lines-1, _columns);
X
X	*lines = _lines - 1;		/* assume index from zero */
X	*columns = _columns;
X}
X
XGetXYLocation(x,y)
Xint *x,*y;
X{
X	/* return the current cursor location on the screen */
X
X	*x = _line;
X	*y = _col;
X}
X
XClearScreen()
X{
X	/* clear the screen: returns -1 if not capable */
X
X	_line = 0;	/* clear leaves us at top... */
X	_col  = 0;
X
X#ifdef UTS
X	if (isatube) {
X		_clear_screen++;	/* queue up for clearing... */
X		return(0);
X	}
X#endif
X
X	if (!_clearscreen)
X		return(-1);
X
X	tputs(_clearscreen, 1, outchar);
X	fflush(stdout);      /* clear the output buffer */
X	return(0);
X}
X
XMoveCursor(row, col)
Xint row, col;
X{
X	/** move cursor to the specified row column on the screen.
X            0,0 is the top left! **/
X
X	char *stuff, *tgoto();
X
X	/* we don't want to change "rows" or we'll mangle scrolling... */
X
X	if (col > COLUMNS) col = COLUMNS;
X	if (col < 0)       col = 0;
X
X#ifdef UTS
X	if (isatube) {
X		at row+1, col+1;
X		_line = row;
X		_col  = col;
X		return(0);
X	}
X#endif
X	if (!_moveto)
X		return(-1);
X
X	if (row == _line) {
X	  if (col == _col)
X	    return(0);				/* already there! */
X
X	  else if (abs(col - _col) < 5) {	/* within 5 spaces... */
X	    if (col > _col)
X	      CursorRight(col - _col);
X	    else 
X	      CursorLeft(_col - col);
X          }
X	  else {		/* move along to the new x,y loc */
X	    stuff = tgoto(_moveto, col, row);
X	    tputs(stuff, 1, outchar);
X	    fflush(stdout);
X	  }
X	}
X	else if (col == _col && abs(row - _line) < 5) {
X	  if (row < _line)
X	    CursorUp(_line - row);
X	  else
X	    CursorDown(row - _line);
X	}
X	else if (_line == row-1 && col == 0) {
X	  putchar('\n');	/* that's */
X	  putchar('\r');	/*  easy! */
X	  fflush(stdout);
X	}
X	else {
X	  stuff = tgoto(_moveto, col, row);
X	  tputs(stuff, 1, outchar);
X	  fflush(stdout);
X	}
X
X	_line = row;	/* to ensure we're really there... */
X	_col  = col;
X
X	return(0);
X}
X
XCursorUp(n)
Xint n;
X{
X	/** move the cursor up 'n' lines **/
X
X	_line = (_line-n > 0? _line - n: 0);	/* up 'n' lines... */
X
X#ifdef UTS
X	if (isatube) {
X		at _line+1, _col+1;
X		return(0);
X	}
X#endif
X	if (!_up)
X		return(-1);
X
X	while (n-- > 0)
X		tputs(_up, 1, outchar);
X
X	fflush(stdout);
X	return(0);
X}
X
X
XCursorDown(n)
Xint n;
X{
X	/** move the cursor down 'n' lines **/
X
X	_line = (_line+n < LINES? _line + n: LINES);	/* down 'n' lines... */
X
X#ifdef UTS
X	if (isatube) {
X		at _line+1, _col+1 ;
X		return(0);
X	}
X#endif
X
X	if (!_down)
X		return(-1);
X
X	while (n-- > 0)
X		tputs(_down, 1, outchar);
X
X	fflush(stdout);
X	return(0);
X}
X
X
XCursorLeft(n)
Xint n;
X{
X	/** move the cursor 'n' characters to the left **/
X
X	_col = (_col - n> 0? _col - n: 0);	/* left 'n' chars... */
X
X#ifdef UTS
X	if (isatube) {
X		at _line+1, _col+1;
X		return(0);
X	}
X#endif
X
X	if (!_left)
X		return(-1);
X
X	while (n-- > 0)
X		tputs(_left, 1, outchar);
X
X	fflush(stdout);
X	return(0);
X}
X
X
XCursorRight(n)
Xint n;
X{
X	/** move the cursor 'n' characters to the right (nondestructive) **/
X
X	_col = (_col+n < COLUMNS? _col + n: COLUMNS);	/* right 'n' chars... */
X
X#ifdef UTS
X	if (isatube) {
X		at _line+1, _col+1;
X		return(0);
X	}
X#endif
X
X	if (!_right)
X		return(-1);
X
X	while (n-- > 0)
X		tputs(_right, 1, outchar);
X
X	fflush(stdout);
X	return(0);
X}
X
X
XStartBold()
X{
X	/** start boldface/standout mode **/
X
X	if (!_setbold)
X		return(-1);
X
X	tputs(_setbold, 1, outchar);
X	fflush(stdout);
X	return(0);
X}
X
X
XEndBold()
X{
X	/** compliment of startbold **/
X
X	if (!_clearbold)
X		return(-1);
X
X	tputs(_clearbold, 1, outchar);
X	fflush(stdout);
X	return(0);
X}
X
X
XStartUnderline()
X{
X	/** start underline mode **/
X
X	if (!_setunderline)
X		return(-1);
X
X	tputs(_setunderline, 1, outchar);
X	fflush(stdout);
X	return(0);
X}
X
X
XEndUnderline()
X{
X	/** the compliment of start underline mode **/
X
X	if (!_clearunderline)
X		return(-1);
X
X	tputs(_clearunderline, 1, outchar);
X	fflush(stdout);
X	return(0);
X}
X
X
XStartHalfbright()
X{
X	/** start half intensity mode **/
X
X	if (!_sethalfbright)
X		return(-1);
X
X	tputs(_sethalfbright, 1, outchar);
X	fflush(stdout);
X	return(0);
X}
X
XEndHalfbright()
X{
X	/** compliment of starthalfbright **/
X
X	if (!_clearhalfbright)
X		return(-1);
X
X	tputs(_clearhalfbright, 1, outchar);
X	fflush(stdout);
X	return(0);
X}
X
XStartInverse()
X{
X	/** set inverse video mode **/
X
X	if (!_setinverse)
X		return(-1);
X
X	tputs(_setinverse, 1, outchar);
X	fflush(stdout);
X	return(0);
X}
X
X
XEndInverse()
X{
X	/** compliment of startinverse **/
X
X	if (!_clearinverse)
X		return(-1);
X
X	tputs(_clearinverse, 1, outchar);
X	fflush(stdout);
X	return(0);
X}
X
Xint
XHasMemlock()
X{
X	/** returns TRUE iff memory locking is available (a terminal
X	    feature that allows a specified portion of the screen to
X	    be "locked" & not cleared/scrolled... **/
X
X	return ( _set_memlock && _clear_memlock );
X}
X
Xstatic int _old_LINES;
X
Xint
XStartMemlock()
X{
X	/** mark the current line as the "last" line of the portion to 
X	    be memory locked (always relative to the top line of the
X	    screen) Note that this will alter LINES so that it knows
X	    the top is locked.  This means that (plus) the program 
X	    will scroll nicely but (minus) End memlock MUST be called
X	    whenever we leave the locked-memory part of the program! **/
X
X	if (! _set_memlock)
X	  return(-1);
X
X	if (! _memory_locked) {
X
X	  _old_LINES = LINES;
X	  LINES -= _line;		/* we can't use this for scrolling */
X
X	  tputs(_set_memlock, 1, outchar);
X	  fflush(stdout);
X	  _memory_locked = TRUE;
X	}
X
X	return(0);
X}
X
Xint
XEndMemlock()
X{
X	/** Clear the locked memory condition...  **/
X
X	if (! _set_memlock)
X	  return(-1);
X
X	if (_memory_locked) {
X	  LINES = _old_LINES;		/* back to old setting */
X  
X	  tputs(_clear_memlock, 1, outchar);
X	  fflush(stdout);
X	  _memory_locked = FALSE;
X	}
X	return(0);
X}
X
X
XWritechar(ch)
Xchar ch;
X{
X	/** write a character to the current screen location. **/
X
X#ifdef UTS
X	char buffer[2];	/* can't output characters! */
X
X	if (isatube) {
X	  buffer[0] = ch;
X	  buffer[1] = '\0';
X
X	  at _line+1, _col+1;
X	  panel (noerase, noinit, noread) {
X	    #ON, buffer, 1#
X	  }
X 	}
X	else
X#endif
X	  putchar(ch);
X
X	if (ch == BACKSPACE)	/* moved BACK one! */
X		_col--;
X	else if (ch >= ' ')	/* moved FORWARD one! */
X		_col++;
X}
X
X/*VARARGS2*/
X
XWrite_to_screen(line, argcount, arg1, arg2, arg3)
Xchar *line;
Xint   argcount, arg1, arg2, arg3;
X{
X	/** This routine writes to the screen at the current location.
X  	    when done, it increments lines & columns accordingly by
X	    looking for "\n" sequences... **/
X
X	switch (argcount) {
X	case 0 :
X		PutLine0(_line, _col, line);
X		break;
X	case 1 :
X		PutLine1(_line, _col, line, arg1);
X		break;
X	case 2 :
X		PutLine2(_line, _col, line, arg1, arg2);
X		break;
X	case 3 :
X		PutLine3(_line, _col, line, arg1, arg2, arg3);
X		break;
X	}
X}
X
XPutLine0(x, y, line)
Xint x,y;
Xchar *line;
X{
X	/** Write a zero argument line at location x,y **/
X
X	register int i;
X
X#ifdef UTS
X	if (isatube) {
X		at x+1, y+1;
X		panel (init=_clear_screen, noread, erase=_clear_screen) {
X		  #ON, line, strlen(line)-1#
X		}
X		_clear_screen = 0;
X		_col += printable_chars(line);
X
X		/* line wrapped around?? */
X		while (_col > COLUMNS) {
X		  _col  -= COLUMNS;
X		  _line += 1;
X		}
X
X		/* now let's figure out if we're supposed to do a "<return>" */
X
X		for (i=0; i < strlen(line); i++)
X			if (line[i] == '\n') {
X				_line++;
X				_col = 0;		/* on new line! */
X			}
X		return(0);
X	}
X#endif
X	MoveCursor(x,y);
X	printf("%s", line);	/* to avoid '%' problems */
X	fflush(stdout);
X	_col += printable_chars(line);
X
X	while (_col > COLUMNS) { 	/* line wrapped around?? */
X		_col -= COLUMNS;
X		_line += 1;
X	}
X
X	/** now let's figure out if we're supposed to do a "<return>" **/
X
X	for (i=0; i < strlen(line); i++)
X		if (line[i] == '\n') {
X			_line++;
X			_col = 0;		/* on new line! */
X		}
X}
X
X/*VARARGS2*/
XPutLine1(x,y, line, arg1)
Xint x,y;
Xchar *line;
Xchar *arg1;
X{
X	/** write line at location x,y - one argument... **/
X
X	char buffer[VERY_LONG_STRING];
X
X	sprintf(buffer, line, arg1);
X
X	PutLine0(x, y, buffer);
X}
X
X/*VARARGS2*/
XPutLine2(x,y, line, arg1, arg2)
Xint x,y;
Xchar *line;
Xchar *arg1, *arg2;
X{
X	/** write line at location x,y - one argument... **/
X
X	char buffer[VERY_LONG_STRING];
X
X	sprintf(buffer, line, arg1, arg2);
X
X	PutLine0(x, y, buffer);
X}
X
X/*VARARGS2*/
XPutLine3(x,y, line, arg1, arg2, arg3)
Xint x,y;
Xchar *line;
Xchar *arg1, *arg2, *arg3;
X{
X	/** write line at location x,y - one argument... **/
X
X	char buffer[VERY_LONG_STRING];
X
X	sprintf(buffer, line, arg1, arg2, arg3);
X
X	PutLine0(x, y, buffer);
X}
X
XCleartoEOLN()
X{
X	/** clear to end of line **/
X#ifdef UTS
X	char buffer[SLEN];
X	register int cols, i = 0;
X
X	if (isatube) {
X
X		for (cols = _col; cols < COLUMNS; cols++)
X			buffer[i++] = ' ';
X
X		buffer[i] = '\0';
X
X		at _line+1, _col+1;
X		panel (noerase, noinit, noread) {
X		  #ON, buffer, strlen(buffer)-1#
X		}
X
X		return(0);
X	}
X#endif
X
X	if (!_cleartoeoln)
X		return(-1);
X
X	tputs(_cleartoeoln, 1, outchar);
X	fflush(stdout);  /* clear the output buffer */
X	return(0);
X}
X
XCleartoEOS()
X{
X	/** clear to end of screen **/
X
X#ifdef UTS
X	register int line_at;
X
X	if (isatube) {
X	  for (line_at = _line; line_at < LINES-1; line_at++) {
X		panel (noread, noinit, noread) {
X	            #@ line_at, 1# #ON, _null_string, COLUMNS# 
X		}
X	  }
X	
X  	  return(0);
X	}
X
X#endif
X	if (!_cleartoeos)
X		return(-1);
X
X	tputs(_cleartoeos, 1, outchar);
X	fflush(stdout);  /* clear the output buffer */
X	return(0);
X}
X
X#ifdef RAWMODE
X
XRaw(state)
Xint state;
X{
X	/** state is either ON or OFF, as indicated by call **/
X
X	if (state == OFF && _inraw) {
X	  (void) ioctl(TTYIN, TCSETAW, &_original_tty);
X	  _inraw = 0;
X	}
X	else if (state == ON && ! _inraw) {
X
X	  (void) ioctl(TTYIN, TCGETA, &_original_tty);	/** current setting **/
X
X	  (void) ioctl(TTYIN, TCGETA, &_raw_tty);    /** again! **/
X#ifdef BSD
X	  _raw_tty.sg_flags &= ~(ECHO | CRMOD);	/* echo off */
X	  _raw_tty.sg_flags |= CBREAK;	/* raw on    */
X#else
X	  _raw_tty.c_lflag &= ~(ICANON | ECHO);	/* noecho raw mode        */
X
X	  _raw_tty.c_cc[VMIN] = '\01';	/* minimum # of chars to queue    */
X	  _raw_tty.c_cc[VTIME] = '\0';	/* minimum time to wait for input */
X
X#endif
X	  (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
X
X	  _inraw = 1;
X	}
X}
X
Xint
XReadCh()
X{
X	/** read a character with Raw mode set! **/
X
X	register int result;
X	char ch;
X
X	result = read(0, &ch, 1);
X
X	return(result == 0? EOF : ch);
X}
X
X#endif
X
Xoutchar(c)
Xchar c;
X{
X	/** output the given character.  From tputs... **/
X	/** Note: this CANNOT be a macro!              **/
X
X	putc(c, stdout);
X}
END_OF_src/curses.c
if test 16822 -ne `wc -c <src/curses.c`; then
    echo shar: \"src/curses.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"src/read_rc.c\" \(18128 characters\)
if test -f src/read_rc.c ; then 
  echo shar: Will not over-write existing file \"src/read_rc.c\"
else
sed "s/^X//" >src/read_rc.c <<'END_OF_src/read_rc.c'
X/**			read_rc.c			**/
X
X/** (C) Copyright 1985, Dave Taylor			**/
X
X/** This file contains programs to allow the user to have a .elmrc file
X    in their home directory containing any of the following: 
X
X	fullname= <username string>
X	maildir = <directory>
X	mailbox = <file>
X	editor  = <editor>
X	savemail= <savefile>
X	calendar= <calendar file name>
X	shell   = <shell>
X	print   = <print command>
X	weedout = <list of headers to weed out>
X	prefix  = <copied message prefix string>
X	pager   = <command to use for displaying messages>
X
X--
X	signature = <.signature file for all outbound mail>
XOR:
X	localsignature = <.signature file for local mail>
X	remotesignature = <.signature file for non-local mail>
X--
X
X	bounceback= <hop count threshold, or zero to disable>
X	timeout = <seconds for main menu timeout or zero to disable>
X	userlevel = <0=amateur, 1=okay, 2 or greater = expert!>
X
X	sortby  = <sent, received, from, size, subject>
X
X	alternatives = <list of addresses that forward to us>
X
X    and/or the logical arguments:
X	
X	autocopy    [on|off]
X	copy        [on|off]	
X	resolve     [on|off]
X	weed        [on|off]
X	noheader    [on|off]
X	titles      [on|off]
X	editout     [on|off]
X	savebyname  [on|off]
X	movepage    [on|off]
X	pointnew    [on|off]
X	hpkeypad    [on|off]
X	hpsoftkeys  [on|off]
X	alwaysleave [on|off]
X	alwaysdel   [on|off]
X	arrow	    [on|off]
X	menus	    [on|off]
X	forms	    [on|off]
X	warnings    [on|off]
X	names	    [on|off]
X	ask	    [on|off]
X	keepempty   [on|off]
X
X
X    Lines starting with '#' are considered comments and are not checked
X    any further!
X
X    Modified 10/85 to know about "Environment" variables..
X    Modified 12/85 for the 'prefix' option
X    Modified  2/86 for the new 3.3 flags
X    Modified  8/86 (was I supposed to be keeping this up to date?)
X**/
X
X#include <stdio.h>
X#include <ctype.h>
X
X#ifdef BSD
X#undef tolower
X#endif
X
X#include "headers.h"
X
Xchar *shift_lower(), *strtok(), *getenv(), *strcpy();
Xvoid   exit();
X
X#define NOTWEEDOUT	0
X#define WEEDOUT		1
X#define ALTERNATIVES	2
X
Xread_rc_file()
X{
X	/** this routine does all the actual work of reading in the
X	    .rc file... **/
X
X	FILE *file;
X	char buffer[SLEN], filename[SLEN];
X	char word1[SLEN], word2[SLEN];
X	register int  i, errors = 0, last = NOTWEEDOUT, lineno = 0;
X
X	sprintf(filename,"%s/%s", home, elmrcfile);
X
X	default_weedlist();
X
X	alternative_addresses = NULL; 	/* none yet! */
X
X	if ((file = fopen(filename, "r")) == NULL) {
X	  dprint0(2,"Warning: User has no \".elmrc\" file (read_rc_file)\n");
X	  return;	/* we're done! */
X	}
X
X	while (fgets(buffer, SLEN, file) != NULL) {
X	  lineno++;
X	  no_ret(buffer);	 	/* remove return */
X	  if (buffer[0] == '#') { 	/* comment       */
X	    last = NOTWEEDOUT;
X	    continue;
X	  }
X	  if (strlen(buffer) < 2) {	/* empty line    */
X	    last = NOTWEEDOUT;
X	    continue;
X	  }
X
X	  breakup(buffer, word1, word2);
X
X	  strcpy(word1, shift_lower(word1));	/* to lower case */
X
X	  if (word2[0] == 0 && (last != WEEDOUT || last != ALTERNATIVES)) {
X	    dprint1(2,"Error: Bad .elmrc entry in users file;\n-> \"%s\"\n",
X		     buffer);
X	    fprintf(stderr, 
X		    "Line %d of your \".elmrc\" is badly formed:\n> %s\n",
X		    lineno, buffer);
X	    errors++;
X	    continue;
X	  }
X	
X	  if (equal(word1,"maildir") || equal(word1,"folders")) {
X	    expand_env(folders, word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "fullname") || equal(word1,"username") ||
X		   equal(word1, "name")) {
X	    strcpy(full_username, word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "prefix")) {
X	    for (i=0; i < strlen(word2); i++)
X	      prefixchars[i] = (word2[i] == '_' ? ' ' : word2[i]);
X	    prefixchars[i] = '\0';
X	   
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "shell")) {
X	    expand_env(shell, word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "sort") || equal(word1, "sortby")) {
X	    strcpy(word2, shift_lower(word2));
X	    if (equal(word2, "sent"))
X	       sortby = SENT_DATE;
X	    else if (equal(word2, "received") || equal(word2,"recieved"))
X	       sortby = RECEIVED_DATE;
X	    else if (equal(word2, "from") || equal(word2, "sender"))
X	       sortby = SENDER;
X	    else if (equal(word2, "size") || equal(word2, "lines"))
X	      sortby = SIZE;
X	    else if (equal(word2, "subject"))
X	      sortby = SUBJECT;
X	    else if (equal(word2, "reverse-sent") || equal(word2,"rev-sent"))
X	       sortby = - SENT_DATE;
X	    else if (strncmp(word2, "reverse-rec",11) == 0 || 
X		     strncmp(word2,"rev-rec",7) == 0)
X	       sortby = - RECEIVED_DATE;
X	    else if (equal(word2, "reverse-from") || equal(word2, "rev-from")
X	          || equal(word2,"reverse-sender")|| equal(word2,"rev-sender"))
X	       sortby = - SENDER;
X	    else if (equal(word2, "reverse-size") || equal(word2, "rev-size")
X	          || equal(word2, "reverse-lines")|| equal(word2,"rev-lines"))
X	      sortby = - SIZE;
X	    else if (equal(word2, "reverse-subject") || 
X		     equal(word2, "rev-subject"))
X	      sortby = - SUBJECT;
X	    else {
X	     if (! errors)
X	       printf("Error reading '.elmrc' file;\n");
X	     printf("Line %d: Don't know what sort key '%s' specifies!\n", 
X		    lineno, word2);
X	     errors++;
X	     continue;
X	   }
X	  }
X	  else if (equal(word1, "mailbox")) {
X	    expand_env(mailbox, word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "editor") || equal(word1,"mailedit")) {
X	    expand_env(editor, word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "savemail") || equal(word1, "saveto")) {
X	    expand_env(savefile, word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "calendar")) {
X	    expand_env(calendar_file, word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "print") || equal(word1, "printmail")) {
X	    expand_env(printout, word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "pager") || equal(word1, "page")) {
X	    expand_env(pager, word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "signature")) {
X	    if (equal(shift_lower(word2), "on") ||
X		equal(shift_lower(word2), "off")) {
X	      fprintf(stderr, 
X	  "\"signature\" used in obsolete way in .elmrc file - ignored!\n\r");
X	      fprintf(stderr,
X   "\t(signature should specify the filename to use rather than on/off)\n\r");
X	    }
X	    else {
X	      expand_env(local_signature, word2);
X	      strcpy(remote_signature, local_signature);
X	      signature = TRUE;
X	    }
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "localsignature")) {
X	    expand_env(local_signature, word2);
X	    signature = TRUE;
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "remotesignature")) {
X	    expand_env(remote_signature, word2);
X	    signature = TRUE;
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "autocopy")) {
X	    auto_copy = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "copy") || equal(word1, "auto_cc")) {
X	    auto_cc = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "names")) {
X	    names_only = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "resolve")) {
X	    resolve_mode = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "weed")) {
X	    filter = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "noheader")) {
X	    noheader = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "titles")) {
X	    title_messages = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "editout")) {
X	    edit_outbound = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "savebyname") || equal(word1, "savename")) {
X	    save_by_name = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "movepage") || equal(word1, "page") ||
X		   equal(word1, "movewhenpaged")) {
X	    move_when_paged = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "pointnew") || equal(word1, "pointtonew")) {
X	    point_to_new = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "keypad") || equal(word1, "hpkeypad")) {
X	    hp_terminal = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "softkeys") || equal(word1, "hpsoftkeys")) {
X	    if (hp_softkeys = is_it_on(word2))
X	      hp_terminal = TRUE;	/* must be set also! */
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "arrow")) {
X	    arrow_cursor = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (strncmp(word1, "form", 4) == 0) {
X	    allow_forms = (is_it_on(word2)? MAYBE : NO);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (strncmp(word1, "menu", 4) == 0) {
X	    mini_menu = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (strncmp(word1, "warning", 7) == 0) {
X	    warnings = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "alwaysleave") || equal(word1, "leave")) {
X	    always_leave = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "alwaysdelete") || equal(word1, "delete")) {
X	    always_del = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "ask") || equal(word1, "question")) {
X	    question_me = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "keep") || equal(word1, "keepempty")) {
X	    keep_empty_files = is_it_on(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "bounce") || equal(word1, "bounceback")) {
X	    bounceback = atoi(word2);
X	    if (bounceback > MAX_HOPS) {
X	      fprintf(stderr,
X	"Warning: bounceback is set to greater than %d (max-hops) - Ignored.\n",
X		       MAX_HOPS);
X	      bounceback = 0;
X	    }
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "userlevel")) {
X	    user_level = atoi(word2);
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "timeout")) {
X	    timeout = atoi(word2);
X	    if (timeout < 10) {
X	      fprintf(stderr,
X	   "Warning: timeout is set to less than 10 seconds - Ignored.\n");
X	      timeout = 0;
X	    }
X	    last = NOTWEEDOUT;
X	  }
X	  else if (equal(word1, "weedout")) {
X	    weedout(word2);
X	    last = WEEDOUT;
X	  }
X	  else if (equal(word1, "alternatives")) {
X	    alternatives(word2);
X	    last = ALTERNATIVES;
X	  }
X	  else if (last == WEEDOUT)	/* could be multiple line weedout */
X	    weedout(buffer);
X	  else if (last == ALTERNATIVES)	/* multi-line addresses   */
X	    alternatives(buffer);
X	  else {
X	    fprintf(stderr, 
X		   "Line %d is undefined in your \".elmrc\" file:\n> %s\n", 
X		   lineno, buffer);
X	    errors++;
X	  }
X	}
X
X	if (debug > 10) 	/** only do this if we REALLY want debug! **/
X	  dump_rc_results();
X
X	if (errors) 
X	  exit(errors);
X}
X	
Xweedout(string)
Xchar *string;
X{
X	/** This routine is called with a list of headers to weed out.   **/
X
X	char *strptr, *header;
X	register int i;
X
X	strptr = string;
X
X	while ((header = strtok(strptr, "\t ,\"'")) != NULL) {
X	  if (strlen(header) > 0) {
X	    if (weedcount > MAX_IN_WEEDLIST) {
X	      fprintf(stderr, "Too many weed headers!  Leaving...\n");
X	      exit(1);
X	    }
X	    if ((weedlist[weedcount] = (char *) pmalloc(strlen(header) + 1)) 
X		== NULL) {
X	      fprintf(stderr,
X		      "Too many weed headers - out of memory!  Leaving...\n");
X	      exit(1);
X	    }
X
X	    for (i=0; i< strlen(header); i++)
X	      if (header[i] == '_') header[i] = ' ';
X
X	    strcpy(weedlist[weedcount], header);
X	    weedcount++;
X	  }
X	  strptr = NULL;
X	}
X}
X
Xalternatives(string)
Xchar *string;
X{
X	/** This routine is called with a list of alternative addresses
X	    that you may receive mail from (forwarded) **/
X
X	char *strptr, *address;
X	struct addr_rec *current_record, *previous_record;
X
X	previous_record = alternative_addresses;	/* start 'er up! */
X	/* move to the END of the alternative addresses list */
X
X	if (previous_record != NULL)
X	  while (previous_record->next != NULL)
X	    previous_record = previous_record->next;
X
X	strptr = (char *) string;
X
X	while ((address = strtok(strptr, "\t ,\"'")) != NULL) {
X	  if (previous_record == NULL) {
X	    previous_record = (struct addr_rec *) pmalloc(sizeof 
X		*alternative_addresses);
X
X	    strcpy(previous_record->address, address);
X	    previous_record->next = NULL;
X	    alternative_addresses = previous_record;
X	  }
X	  else {
X	    current_record = (struct addr_rec *) pmalloc(sizeof 
X		*alternative_addresses);
X	  
X	    strcpy(current_record->address, address);
X	    current_record->next = NULL;
X	    previous_record->next = current_record;
X	    previous_record = current_record;
X	  }
X	  strptr = (char *) NULL;
X	}
X}
X
Xdefault_weedlist()
X{
X	/** Install the default headers to weed out!  Many gracious 
X	    thanks to John Lebovitz for this dynamic method of 
X	    allocation!
X	**/
X
X	static char *default_list[] = { ">From", "In-Reply-To:",
X		       "References:", "Newsgroups:", "Received:",
X		       "Apparently-To:", "Message-Id:", "Content-Type:",
X		       "From", "X-Mailer:", "*end-of-defaults*", NULL
X		     };
X
X	for (weedcount = 0; default_list[weedcount] != NULL; weedcount++) {
X	  if ((weedlist[weedcount] = (char *)
X	      pmalloc(strlen(default_list[weedcount]) + 1)) == NULL) {
X	    fprintf(stderr, 
X	       "\n\rNot enough memory for default weedlist.  Leaving.\n\r");
X	    leave(1);
X	  }
X	  strcpy(weedlist[weedcount], default_list[weedcount]);
X	}
X}
X
Xint
Xmatches_weedlist(buffer)
Xchar *buffer;
X{
X	/** returns true iff the first 'n' characters of 'buffer' 
X	    match an entry of the weedlist **/
X	
X	register int i;
X
X	for (i=0;i < weedcount; i++)
X	  if (strncmp(buffer, weedlist[i], strlen(weedlist[i])) == 0) 
X	    return(1);
X
X	return(0);
X}
X
Xbreakup(buffer, word1, word2)
Xchar *buffer, *word1, *word2;
X{
X	/** This routine breaks buffer down into word1, word2 where 
X	    word1 is alpha characters only, and there is an equal
X	    sign delimiting the two...
X		alpha = beta
X	    For lines with more than one 'rhs', word2 is set to the
X	    entire string...
X	**/
X
X	register int i;
X	
X	for (i=0;i<strlen(buffer) && isalpha(buffer[i]); i++)
X	  word1[i] = buffer[i];
X
X	word1[i++] = '\0';	/* that's the first word! */
X
X	/** spaces before equal sign? **/
X
X	while (buffer[i] == ' ' || buffer[i] == '\t') i++;
X
X	if (buffer[i] == '=') i++;
X
X	/** spaces after equal sign? **/
X
X	while (buffer[i] == ' ' || buffer[i] == '\t') i++;
X
X	if (i < strlen(buffer))
X	  strcpy(word2, (char *) (buffer + i));
X	else
X	  word2[0] = '\0';
X}
X
Xexpand_env(dest, buffer)
Xchar *dest, *buffer;
X{
X	/** expand possible metacharacters in buffer and then copy
X	    to dest... 
X	    This routine knows about "~" being the home directory,
X	    and "$xxx" being an environment variable.
X	**/
X
X	char  *word, *string, next_word[SLEN];
X	
X	if (buffer[0] == '/') {
X	  dest[0] = '/';
X	  dest[1] = '\0';
X	}
X	else
X	  dest[0] = '\0';
X
X	string = (char *) buffer;
X
X	while ((word = strtok(string, "/")) != NULL) {
X	  if (word[0] == '$') {
X	    next_word[0] = '\0';
X	    if (getenv((char *) (word + 1)) != NULL)
X	    strcpy(next_word, getenv((char *) (word + 1)));
X	    if (strlen(next_word) == 0)
X	      leave(fprintf(stderr, 
X		    "\n\rCan't expand environment variable '%s'\n\r",
X		    word));
X	  }
X	  else if (word[0] == '~' && word[1] == '\0')
X	    strcpy(next_word, home);
X	  else
X	    strcpy(next_word, word);
X
X	  sprintf(dest, "%s%s%s", dest, 
X		 (strlen(dest) > 0 && lastch(dest) != '/' ? "/":""),
X		 next_word);
X
X	  string = (char *) NULL;
X	}
X}
X
X#define on_off(s)	(s == 1? "ON" : "OFF")
Xdump_rc_results()
X{
X
X	register int i;
X
X	fprintf(debugfile, "\n\n\n\n");
X	fprintf(debugfile, "folders = %s\n", folders);
X	fprintf(debugfile, "mailbox = %s\n", mailbox);
X	fprintf(debugfile, "editor = %s\n", editor);
X	fprintf(debugfile, "printout = %s\n", printout);
X	fprintf(debugfile, "savefile = %s\n", savefile);
X	fprintf(debugfile, "calendar_file = %s\n", calendar_file);
X	fprintf(debugfile, "prefixchars = %s\n", prefixchars);
X	fprintf(debugfile, "shell = %s\n", shell);
X	fprintf(debugfile, "pager = %s\n", pager);
X	fprintf(debugfile, "\n");
X	fprintf(debugfile, "mini_menu = %s\n", on_off(mini_menu));
X	fprintf(debugfile, "mbox_specified = %s\n", on_off(mbox_specified));
X	fprintf(debugfile, "check_first = %s\n", on_off(check_first));
X	fprintf(debugfile, "auto_copy = %s\n", on_off(auto_copy));
X	fprintf(debugfile, "filter = %s\n", on_off(filter));
X	fprintf(debugfile, "resolve_mode = %s\n", on_off(resolve_mode));
X	fprintf(debugfile, "auto_cc = %s\n", on_off(auto_cc));
X	fprintf(debugfile, "noheader = %s\n", on_off(noheader));
X	fprintf(debugfile, "title_messages = %s\n", on_off(title_messages));
X	fprintf(debugfile, "hp_terminal = %s\n", on_off(hp_terminal));
X	fprintf(debugfile, "hp_softkeys = %s\n", on_off(hp_softkeys));
X	fprintf(debugfile, "save_by_name = %s\n", on_off(save_by_name));
X	fprintf(debugfile, "move_when_paged = %s\n", on_off(move_when_paged));
X	fprintf(debugfile, "point_to_new = %s\n", on_off(point_to_new));
X	fprintf(debugfile, "bounceback = %s\n", on_off(bounceback));
X	fprintf(debugfile, "signature = %s\n", on_off(signature));
X	fprintf(debugfile, "always_leave = %s\n", on_off(always_leave));
X	fprintf(debugfile, "always_del = %s\n", on_off(always_del));
X	fprintf(debugfile, "arrow_cursor = %s\n", on_off(arrow_cursor));
X	fprintf(debugfile, "names = %s\n", on_off(names_only));
X	fprintf(debugfile, "warnings = %s\n", on_off(warnings));
X	fprintf(debugfile, "question_me = %s\n", on_off(question_me));
X	fprintf(debugfile, "keep_empty_files = %s\n", 
X			   on_off(keep_empty_files));
X
X	fprintf(debugfile, "\n** userlevel = %s **\n\n", user_level);
X
X	fprintf(debugfile, "Weeding out the following headers;\n");
X	for (i=0; i < weedcount; i++) 
X	  fprintf(debugfile, "\t\"%s\"\n", weedlist[i]);
X	
X	fprintf(debugfile, "\n\n");
X}
X
Xis_it_on(word)
Xchar *word;
X{
X	/** Returns TRUE if the specified word is either 'ON', 'YES'
X	    or 'TRUE', and FALSE otherwise.   We explicitly translate
X	    to lowercase here to ensure that we have the fastest
X	    routine possible - we really DON'T want to have this take
X	    a long time or our startup will be major pain each time.
X	**/
X
X	static char mybuffer[NLEN];
X	register int i, j;
X
X	for (i=0, j=0; word[i] != '\0'; i++)
X	  mybuffer[j++] = isupper(word[i]) ? tolower(word[i]) : word[i];
X	mybuffer[j] = '\0';
X
X	return(  (strncmp(mybuffer, "on",   2) == 0) ||
X		 (strncmp(mybuffer, "yes",  3) == 0) ||
X		 (strncmp(mybuffer, "true", 4) == 0)
X	      );
X}
X	
X
X	
X
X
END_OF_src/read_rc.c
if test 18128 -ne `wc -c <src/read_rc.c`; then
    echo shar: \"src/read_rc.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: End of archive 16 \(of 19\).
cp /dev/null ark16isdone
DONE=true
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
    if test ! -f ark${I}isdone ; then
	echo shar: You still need to run archive ${I}.
	DONE=false
    fi
done
if test "$DONE" = "true" ; then
	echo You have unpacked all 19 archives.
	echo "See the Instructions file"
	rm -f ark[1-9]isdone ark[1-9][0-9]isdone
fi
##  End of shell archive.
exit 0