[comp.unix.i386] CLED 2.5 SysV/386 part 01/03

pcg@cs.aber.ac.uk (Piercarlo Grandi) (08/28/90)

This is the implementation of CLED, a line dicipline for System V/386
3.2 that implements command history in the kernel. It originally came
from Atari Corp. for Xenix; I have worked on it a lot to simplify and
clean it, and to make it more conforming to the Installable Driver
scheme of System V/386. I use it all the time, even if it is not the
msot elegant thing in the world :-). Well, it is surely more convenient
and efficient than command line editing libraries attached to shells and
other programs.

It should be easily modified for Xenix and SCO Unix; I run it under ENIX
rev. A, which is a fairly standard version of AT&T Systm V/386.

	Usual disclaimer: this has nothing to do with the University
	College of Wales, which has not aided or funded in any way the
	work on this software. It is entirely part of my own research
	activity, supported and funded entirely by myself. I give many
	thanks to the College however for providing me with news access,
	which makes this posting possible.

Many thanks again to the people at Atari Corp. that wrote and posted
the original version.

-------------------------cut here---------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 3)."
# Contents:  Makefile Master Node README System cled.h cledio.h
#   config.h kernel_space.c patchlevel.h scled.c space.c
# Wrapped by sw@aware on Tue Aug 28 13:36:09 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1356 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# $Id: Makefile,v 2.5 90/08/28 13:35:06 sw Exp $
X
XDEV		=cled
XSYS		=/usr/include/sys
XLSYS		=/usr/local/include/sys
XPACK		=/etc/conf/pack.d
XKFLAGS		=-DINKERNEL
XCFLAGS   	=-O -Zp4 -I$(LSYS)
XLIBS		=$$LDPATH -lmisc -lmalloc -lc_s
X
XCC 		=cc
X
Xall:		s$(DEV) Driver.o $(DEV) #$(DEV)dump
X
XDriver.o:	$(DEV).o;		ln $? $@
XSpace.c:	space.c;		ln $? $@
X
X$(DEV).o: 	$(DEV).c $(LSYS)/$(DEV).h $(LSYS)/$(DEV)io.h
X	$(CC) $(CFLAGS) $(KFLAGS) -c $(DEV).c
X
Xs$(DEV): 	s$(DEV).c $(LSYS)/$(DEV)io.h
X	$(CC) $(CFLAGS) -o s$(DEV) s$(DEV).c $(LIBS)
X
X$(DEV):		$(DEV).c space.o $(LSYS)/$(DEV).h $(LSYS)/$(DEV)io.h config.h
X	$(CC) $(CFLAGS) -o $(DEV) $(DEV).c space.o
X	rm -f $(DEV).o space.o
X
Xspace.o: 	space.o $(LSYS)/$(DEV).h $(LSYS)/$(DEV)io.h config.h
X	$(CC) $(CFLAGS) $(KFLAGS) -c space.c
X	
X#$(DEV)dump: 	$(DEV)dump.c $(LSYS)/$(DEV)io.h $(LSYS)/$(DEV).h
X#	$(CC) $(CFLAGS) $(KFLAGS) -o $(DEV)dump $(DEV)dump.c $(LIBS)
X
X$(SYS)/$(DEV).h:	$(LSYS)/$(DEV).h;	ln $? $@
X$(SYS)/$(DEV)io.h:	$(LSYS)/$(DEV)io.h;	ln $? $@
X$(LSYS)/$(DEV).h:	$(DEV).h;		cp $? $@
X$(LSYS)/$(DEV)io.h:	$(DEV)io.h;		cp $? $@
X
Xinstall:	$(PACK)/kernel/space.c
Xinstall:	$(SYS)/$(DEV).h $(SYS)/$(DEV)io.h
Xinstall:	Master System Driver.o Space.c Node Name
X	$(CONF)idinstall -kea -msopn $(DEV)
X	$(CONF)idmknod -s; chmod a=rw /dev/$(DEV)
X
X$(PACK)/kernel/space.c: kernel_space.c
X	@echo You must still change $@ according to $?
END_OF_FILE
if test 1356 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'Master' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Master'\"
else
echo shar: Extracting \"'Master'\" \(29 characters\)
sed "s/^X//" >'Master' <<'END_OF_FILE'
Xcled	Ii	ico	cled	0	0	1	32	-1
END_OF_FILE
if test 29 -ne `wc -c <'Master'`; then
    echo shar: \"'Master'\" unpacked with wrong size!
fi
chmod +x 'Master'
# end of 'Master'
fi
if test -f 'Node' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Node'\"
else
echo shar: Extracting \"'Node'\" \(14 characters\)
sed "s/^X//" >'Node' <<'END_OF_FILE'
Xcled	cled	c	0
END_OF_FILE
if test 14 -ne `wc -c <'Node'`; then
    echo shar: \"'Node'\" unpacked with wrong size!
fi
chmod +x 'Node'
# end of 'Node'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(4246 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X$Id: README,v 2.5 90/08/26 11:31:46 sw Exp $
X
XThis is a line discipline that implements input history management.  It
Xwas written originally by Lyle Rains of Atari for RT-11, ported by Dave
XSheppard of Atari to Xenix/386, and ported by Piercarlo Grandi to System
XV/386 3.2, as well as _much_ cleaned up and modified.
X
XThis README file has been written entirely by Piercarlo Grandi, and so
Xare all the comments herein.
X
XFirst of all, while I think this is a very useful driver, and though I
Xhave struggled a lot to make it more like I would have done it, I have
Xnot substantially changed it, even if there are a series of things that
XI would have done very differently.
X
XThe current advantages of CLED are:
X
X    * It is fully kernel resident, and will keep in the history buffer
X    all input, by whatever program.  There is no need to add an
X    inefficient raw or cbreak mode library to each program or to hack
X    with ptys to have history processing.
X
X    * It is quite fast, and surely has less overhead than other input
X    history mechanisms.
X
X    * It can be easily ported to different types of UNIX, and will work
X    virtually unchanged on any System V (or V7) derivative.
X
X    * It will get out of the way when not needed, e.g.  for raw or
X    cbreak input.
X
X    * It is free.
X
XThe disadvantages are:
X
X    * The history mechanism is pretty simple; there are no pattern
X    searches, for example.  This is probably a feature.
X
X    * It occupies wired down kernel space.  This is probably a feature,
X    because any other interactive history mechanism would probably cost
X    vastly more in both space and time overheads.
X
X    * It is not easily extensible, as it is linked with the kernel.
X    Again, this is probably a feature.
X
X    * There is no command or file name completion.  This can be
X    efficiently implemented by any interested program on top of CLED by
X    using the VEOL2 character as trigger.
X
XThere are some things that I would have done differently:
X
X    * Design and coding are often quite opaque, and source and object
X    sizes too large (4000 lines!).  Cleverer design and coding would
X    probably shrink both substantially.
X
X    * CLED is piggybacked onto line discipline 0; it should be
X    standalone, to allow for getting rid of the standard line discipline
X    completely.
X
X    * Buffers should have been stolen from the buffer cache, instead of
X    statically allocated (sptalloc() is no help because of its
X    impossibly large granularity).
X
X    * Currently when the user logs out the history is not cleared,
X    because technically the tty device is not closed.  This is a
X    security hazard, even if not as bad as it looks, because CLED
X    disables itself during not echoed or raw input, so that passwords
X    are not recorded (passwords passed as arguments to a command are a
X    security hazard anyhow).
X
X    * Saving, resetting, and restoring the current history buffer should
X    therefore become better supported.
X
X    * The ioctl(2) codes should allow setting key bindings and terminal
X    capabilities independently.  In general the ioctl(2) interface is
X    quite clumsy.
X
X    * The scled(1) command should be completely rewritten.
X
XThere are also a few known problems, but they are usually not mistakes
Xbut rather compromises (e.g.  when inserting tabs in the middle of the
Xline, the check on line length is circumvented).  Surely there are also
Xlots of real bugs.
X
XTo install CLED, have a look at the "Makefile" (should be ok on most any
XUNIX), and at files "cled.h" and "space.c".  It is suggested that you do
Xnot change the configuration options at the top of "cled.h"; not only I
Xhave not tested other configurations, but enabling the most
Xsophisticated options of CLED substantially enlarges it.  In particular,
Xunless you know better, do not enable SPTALLOC.
X
XAs to the buffer sizes, I think the ones given are OK for most anybody;
Xnote that CLED will not allow you to type a line longer than the current
Xscreen size, so the MAXLINE parameter is really the maximum number of
Xcolumns on a terminal, and 132 is therefore sufficient.  As to
XMAXPROMPT, I hope you do not use garish long prompts...  In any case
Xthis is the number of characters remembered in the prompt, not its
Xmaximum size.
END_OF_FILE
if test 4246 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
chmod +x 'README'
# end of 'README'
fi
if test -f 'System' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'System'\"
else
echo shar: Extracting \"'System'\" \(23 characters\)
sed "s/^X//" >'System' <<'END_OF_FILE'
Xcled	Y	6	0	0	0	0	0	0	0
END_OF_FILE
if test 23 -ne `wc -c <'System'`; then
    echo shar: \"'System'\" unpacked with wrong size!
fi
chmod +x 'System'
# end of 'System'
fi
if test -f 'cled.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cled.h'\"
else
echo shar: Extracting \"'cled.h'\" \(6029 characters\)
sed "s/^X//" >'cled.h' <<'END_OF_FILE'
X/*
X    $Id: cled.h,v 2.5 90/08/26 11:33:56 sw Exp $
X*/
X/*
X    This should be set, if compiling as line discipline, in the command line
X*/
X
X#ifndef M_KERNEL
X#   define M_KERNEL	0
X#endif
X
X/*
X    These are booleans and describe the environment in which CLED
X    is compiled and run. Even if you are on a 386 with a Unix that
X    has sptalloc()/sptfree() you will normally not want to use it,
X    because it allocates memory in page (4096 bytes) chunks.
X*/
X
X#define M_I386		1	/* Running on a 386 ?			*/
X#define M_UNIX		1	/* System V/SCO Unix ? (or Xenix?)	*/
X#define M_ATT		1	/* AT&T flavour of System V ?		*/
X#define M_SPTALLOC	0	/* Kernel has, and we should use, it	*/
X
X/*
X    These are boolean options.  DEBUG should normally be 0.  The code
X    compiled in if CLEDIO is true is large; if you don't need to change
X    the default terminal capabilities and key bindings, set it to 0.
X    BREAKTHRU compiles in a nother large chunk of code that will
X    automatically reprint the current line if a write to the tty garbles
X    it.  You should normally set this to 0 and just explicitly request a
X    redraw in the rare event this happens.  MULTILB will dynamically
X    allocate a separate history buffer per process, not just one per
X    tty.  This is usually not what you want, and makes code and data
X    space grow.
X*/
X
X#define DEBUG		0	/* Compile in debugging helps		*/
X
X#define CLEDIO		1	/* Include ioctls to change defaults ?	*/
X#define BREAKTHRU	0	/* Auto reprint on broadcasts ?		*/
X#define MULTILB		0	/* Separate history per process ?	*/
X#define VERBOSE		0	/* Print a msg each time CLED opens	*/
X
X#define COLUMNS		80	/* Default number of columns		*/
X
X/*
X    These set sizes of various buffers. Suitable values depend on the
X    amount of memory you want to devote to CLED, and its availability.
X    For a 386 you may want these to be 1024,32,134,64, and for a 286
X    they may be 256,16,82,64.
X*/
X
X#define MAXPROMPT	16	/* Size of prompt buffer		*/
X#define MAXLINE		132	/* Size of command line buffer		*/
X#define MAXHISTORY	1024	/* Size of history buffer		*/
X#if !M_SPTALLOC
X#   define TCAP_SIZE	64	/* max length of all terminal escapes	*/
X#endif
X
X/* End of user adjustable parameters */
X
X/*
X    Under which termio conditions CLED will operate
X*/
X
X#define CLEDOFF(flags)	(((flags) & CLEDFLAGS) != CLEDFLAGS)
X
X#if 0
X#if M_KERNEL
X#   undef MULTILB
X#   undef M_SPTALLOC
X#   define M_SPTALLOC	0
X#   define MULTILB	0
X#   if !defined(TCAP_SIZE)
X#	define TCAP_SIZE	64
X#   endif
X#endif
X#endif
X
X#define LD_DONE	    0x0001	/* flag indicating read complete	*/
X#define LD_QUIT	    0x0002	/* completed under QUIT char		*/
X#define LD_INTR     0x0004	/* completed under INTR char		*/
X#define LD_EOF	    0x0008	/* completed under EOF			*/
X#define LD_DIRTY    0x0010	/* command buffer has been changed	*/
X#define LD_INSERT   0x0020	/* insert mode				*/
X
X#define TB_NOLINE   0x0001	/* not using this discipline		*/
X#define TB_OPEN	    0x0002	/* tty buff is open			*/
X#define TB_READING  0x0004	/* read currently in progress		*/
X#define TB_WRITING  0x0008	/* write currently in progress		*/
X#define TB_INSERT   0x0010	/* insert mode				*/
X#define TB_OVERUN   0x0020	/* input buffer overrun			*/
X#define TB_OPENING  0x0040	/* tty buf is opening			*/
X#define TB_FLUSHIT  0x0080	/* flush the input que			*/
X
X/*
X    if last flag is greater than 0x8000, change flags from short to long
X*/
X
X#ifdef M_I386
X#   pragma pack(1)
X#endif
X
Xstruct led_buf
X{
X#if MULTILB
X    struct led_buf          *next;
X    struct led_buf          *last;
X    struct proc             *proc;
X#endif
X
X    struct tty_buf          *tbp;	/* Tty buf that owns us		*/
X
X    unchar                  prompt[MAXPROMPT+1]; /* +1: Final '\0'	*/
X    unchar                  promptlen;	/* Current length of prompt	*/
X
X    unchar		    line[MAXLINE+2]; /* +2: Left&right mark	*/
X    unchar                  *lineend;	/* End of line in buf		*/
X    unchar                  *lcurs;	/* Start of gap in buf		*/
X    unchar                  *rcurs;	/* End of gap in buf		*/
X    unchar                  *owed;	/* Part of line left over	*/
X
X    int			    current;	/* Cursor position		*/
X    int			    lastchar;	/* Last char in line buf	*/
X
X    unchar                  history[MAXHISTORY+1]; /* +1: Final '\0'	*/
X    unchar                  *historyend;/* End of history buffer	*/
X    int                     lastline;	/* Last line in history buf	*/
X    int                     matchlen;	/* Length of match string	*/
X
X    unsigned		    flags;
X    unsigned		    state;
X
X    unchar                  c;		/* Character being input	*/
X
X#if MULTILB
X    int			    pid;
X    int			    ppid;
X#endif
X};
X
X#ifdef M_I386
X#   pragma pack()
X#endif
X
Xstruct tty_buf
X{
X    struct tty_buf          *next;
X    struct tty_buf          *last;
X
X    struct led_buf          *lbp;	/* Pointer to line buffer	*/
X    struct tty              *ttyp;	/* The tty we are serving	*/
X
X    int			    cols;	/* Terminal line width		*/
X
X    unsigned		    iflag;
X    unsigned		    oflag;
X    unsigned		    lflag;
X    unsigned		    cflag;
X    char		    cc[NCC + 2];
X
X    unsigned		    flags;
X    char		    dorefresh;	/* Refresh current line soon	*/
X    char		    readsleep;	/* Sleeping while reading	*/
X
X    struct clist	    broadcast;
X
X    /*
X	Keyboard map, and terminal capability index and table
X	for this tty.
X    */
X    unchar		    keymap[CLEKEY_MAX];
X
X    char		    *tcap[TCAP_COUNT];
X
X    int			    tclen;
X#if M_SPTALLOC
X    unchar		    *tcstrings;
X#else
X    unchar		    tcstrings[TCAP_SIZE];
X#endif
X};
X
X#if M_SPTALLOC && M_KERNEL
X#   if M_UNIX
X	extern caddr_t	*sptalloc(/* int pages,int mode,int base,int flag */);
X	extern void	sptfree(/* char *va,int npages,int freeflag */);
X
X#	define Sptalloc(bytes)	    sptalloc(btopt(bytes),PG_P,0,0)
X#	define Sptfree(addr,bytes)  sptfree(addr,btopt(bytes),1)
X#   else
X#	define Sptalloc(bytes)	    sptalloc(bytes)
X#	define Sptfree(addr,bytes)  sptfree(addr,bytes,1)
X#   endif
X#else
X#   if !M_KERNEL
X#	define Sptalloc(size)	    malloc(size)
X#	define Sptfree(addr,size)   free(addr)
X#   endif
X#endif
END_OF_FILE
if test 6029 -ne `wc -c <'cled.h'`; then
    echo shar: \"'cled.h'\" unpacked with wrong size!
fi
chmod +x 'cled.h'
# end of 'cled.h'
fi
if test -f 'cledio.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cledio.h'\"
else
echo shar: Extracting \"'cledio.h'\" \(6898 characters\)
sed "s/^X//" >'cledio.h' <<'END_OF_FILE'
X/*
X    $Id: cledio.h,v 2.5 90/08/26 11:35:00 sw Exp $
X*/
X
X/*
X    CLED will be active only if this options are set
X*/
X
X#define CLEDFLAGS	(ICANON|ECHO|ECHOE|ECHOK)
X
X/*
X    Terminal capabilities remembered by CLED
X*/
X
X#define TCAP_CLREOL_STR		"\033[K"	/* clear to eol		*/
X#define TCAP_SETINV_STR		"\033[7m"	/* set inverse video	*/
X#define TCAP_SETNORM_STR	"\033[m"	/* set normal video	*/
X#define TCAP_SAVE_STR		"\0337"		/* save cursor pos and attr */
X#define TCAP_RESTORE_STR	"\0338"		/* restore pos and attr	*/
X#define TCAP_FLASH_STR		"\007"		/* ring bell or similar	*/
X
X#define TCAP_CLREOL	0
X#define TCAP_SETINV	1
X#define TCAP_SETNORM	2
X#define TCAP_SAVE	3
X#define TCAP_RESTORE	4
X#define TCAP_FLASH	5
X#define TCAP_COUNT	6			/* last one indicates total */
X
X/*
X    ioctl codes available
X*/
X
X#define LDIOC	    ('D'<<8)
X
X/*
X    Ioctls on the line discipline itself
X*/
X
X#define LDGETCOLS   (LDIOC|14)	    /* Get terminal line length		*/
X#define LDSETCOLS   (LDIOC|15)	    /* Set terminal line length		*/
X
X#define LDGETBF	    (LDIOC|16)	    /* get bindings & capabilities	*/
X#define LDSETBF	    (LDIOC|17)	    /* set bindings & capabilities	*/
X
X#define LDGETHB	    (LDIOC|18)	    /* get history buffer		*/
X#define LDSETHB	    (LDIOC|19)	    /* set history buffer		*/
X
X/*
X    Ioctls on the CLED driver in general
X*/
X
X#define LDGETS	    (LDIOC|20)	    /* get cled stats			*/
X
X#define LDGETB	    (LDIOC|21)	    /* dump its guts (debug mode only)	*/
X#define LDGETTTY    (LDIOC|22)	    /* dump a tty struct (debug mode only) */
X#define LDGETC	    (LDIOC|23)	    /* dump contents of a clist (debug only) */
X
X/*
X    Error codes returned from ioctl functions
X*/
X
X#define ERR_NOTTYBUF	12	    /* ENOMEM no more ttybufs available */
X#define ERR_NOLEDBUF	11	    /* EAGAIN no more ledbufs available */
X#define ERR_NOLBASS	19	    /* ENODEV no led buf assigned to process */
X#define ERR_BADPARAM	22	    /* EINVAL bad paramater value */
X#define ERR_BADIOCTL	33	    /* EDOM bad ioctl function */
X
X/*
X    Pass the address of this struct to LDGETS
X*/
X
Xstruct cle_stats
X{
X    int		    ledbufs;	    /* max number of led_buffers	*/
X    int		    ttybufs;	    /* max number of tty_buffers	*/
X    int		    promptsize;	    /* size of prompt buffer		*/
X    int		    linesize;	    /* size of command buffer		*/
X    int		    histsize;	    /* size of history buffer		*/
X    int		    multi_lb;	    /* t/f flag indicating multi-lb mode */
X    int		    spt;	    /* t/f flag indicating using sptalloc */
X    int		    tcapsize;	    /* max length of all ascii strings	*/
X    int		    ledbufs_used;   /* number of led_buf's in use	*/
X    int		    ttybufs_used;   /* number of tty_buf's in use	*/
X    int		    line;	    /* cled's line discipline number	*/
X    char	    vers[4];	    /* version #			*/
X};
X
X/*
X    Pass the address of this struct to LDGETB/LDSETB
X*/
X
Xstruct cle_buf
X{
X    int		    lbsize;
X    int		    tbsize;
X    struct led_buf  *lbbase;
X    struct led_buf  *lbfree;
X    struct tty_buf  *tbbase;
X    struct tty_buf  *tbused;
X    struct tty_buf  *tbfree;
X    struct proc	    *procbase;
X};
X
X/*
X    Pass this struct for LDGETF/LDSETF.
X
X    The following structure is passed to the ioctl routine to
X    /dev/cled to assign the key bindings and the TCAP sequences
X    (and other strings) desired for various functions.
X
X    If the ioctl completes with an error, then the len fields of
X    the struct will have been changed to an index into the
X    respective buffer at which the error occured (the driver sets
X    the value).
X
X    The key buffer immediately follows the set_key struct and the
X    TCAP buffer immediately follows the key buffer.
X
X    The key buffer contains pairs of chars; the first is the key
X    number and the second is the function number.  The kdbuf_len
X    entry in the set_key struct contains the total number of these
X    pairs of chars.  Any of the control keys and/or keypad keys can
X    be set to any function at any time.  New definitions replace
X    previous definitions.  Keys not explicitly defined in the
X    buffer are left defined to whatever they were.
X
X    The TCAP buffer consists of a stream of null terminated strings
X    preceeded by the number of the sequence to which the string
X    belongs.  If any TCAP sequence is defined, then ALL the
X    sequences are first reset to their defaults and then replaced
X    with the new definitions.  That is, you can change one or all,
X    but unlike the key definitions, you cannot change just one
X    without affecting all the others.
X*/
X
Xstruct set_key
X{
X    int                     modes;	    /* default mode bits	    */
X    int                     kdbuf_len;	    /* key buffer length (in items) */
X    int                     tcapbuf_len;    /* length of escapes (in chars) */
X};
X
X/*
X    We implement a very contrived set of key bindings; we have
X    the 32 control characters, then 96 meta characters, then
X    DEL. We don't provide for bindint to x or M-C-x, only
X    either C-x or M-x.
X
X    To bind to M-x, use CLEKEY_ESC(x), to bind to C-x, use CLEKEY_CTL(x).
X*/
X
X#define CLEKEY_CHAR(c)	((c) >= ' ' && (c) <= '~')
X
X#define CLEKEY_CMD(c)	((c)&0x7F)
X#define CLEKEY_ESC(c)	((c)&0x7F)
X#define CLEKEY_CTL(c)	((c)&0x1F)
X#define CLEKEY_DEL	0x7F
X
X#define CLEKEY_MAX	0x80
X
X/*
X    default modes
X*/
X
X#define CLEMODE_INSERT	0x01	/* insert mode */
X#define CLEMODE_OVER    0x02	/* overstrike mode */
X
X/*
X    Editor functions: (don't change the order of these)
X*/
X
X#define CLEFUN_CHAR	0x00	/* insert character into buffer		*/
X#define CLEFUN_INSERT	0x01	/* toggle insert/overstrike mode	*/
X#define CLEFUN_GOTOBOL	0x02	/* goto beginning of line		*/
X#define CLEFUN_GOTOEOL	0x03	/* goto end of line			*/
X#define CLEFUN_DELWLFT	0x04	/* delete word to left of cursor	*/
X#define CLEFUN_DELWRIT	0x05	/* delete word to right of cursor	*/
X#define CLEFUN_DELBOL	0x06	/* delete from cursor to beginning of line */
X#define CLEFUN_DELEOL	0x07	/* delete from cursor to end of line	*/
X#define CLEFUN_CURSL	0x08	/* move cursor left 1 position		*/
X#define CLEFUN_CURSR	0x09	/* move cursor right 1 position		*/
X#define CLEFUN_DELCLFT	0x0A	/* delete char left of cursor		*/
X#define CLEFUN_DELCRIT	0x0B	/* delete char under cursor		*/
X#define CLEFUN_REFRESH	0x0C	/* reprint the current line		*/
X#define CLEFUN_PREVIOUS	0x0D	/* recall previous command		*/
X#define CLEFUN_NEXT	0x0E	/* recall next command			*/
X#define CLEFUN_FIND	0x0F	/* find matching string			*/
X#define CLEFUN_NEWLINE	0x10	/* end of line				*/
X#define CLEFUN_ESCAPE	0x11	/* "escape" the next character		*/
X#define CLEFUN_NOP	0x12	/* nop					*/
X#define CLEFUN_BELL	0x13	/* ring bell				*/
X#define CLEFUN_SKIPWL	0x14	/* skip word left			*/
X#define CLEFUN_SKIPWR	0x15	/* skip word right			*/
X#define CLEFUN_PURGE	0x16	/* purge all typeahead			*/
X#define CLEFUN_META	0x17	/* access chars with 8th bit on		*/
X#define CLEFUN_ANSI	0x18	/* parse ansi cursor sequence		*/
X#define CLEFUN_MAX	0x19	/* number of functions			*/
END_OF_FILE
if test 6898 -ne `wc -c <'cledio.h'`; then
    echo shar: \"'cledio.h'\" unpacked with wrong size!
fi
chmod +x 'cledio.h'
# end of 'cledio.h'
fi
if test -f 'config.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config.h'\"
else
echo shar: Extracting \"'config.h'\" \(301 characters\)
sed "s/^X//" >'config.h' <<'END_OF_FILE'
X/* fake config.h used to test compiling space.c */
X
X#define	CLED		1
X#define	CLED_CNTLS	1
X#define	CLED_UNITS	6
X#define	CLED_CHAN	-1
X#define	CLED_TYPE	0
X
X#define	CLED_0		6
X#define	CLED_0_VECT	0
X#define	CLED_0_SIOA	0
X#define	CLED_0_EIOA	0
X#define	CLED_0_SCMA	0
X#define	CLED_0_ECMA	0
X
X#define	NCLEPROCS	1
END_OF_FILE
if test 301 -ne `wc -c <'config.h'`; then
    echo shar: \"'config.h'\" unpacked with wrong size!
fi
chmod +x 'config.h'
# end of 'config.h'
fi
if test -f 'kernel_space.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kernel_space.c'\"
else
echo shar: Extracting \"'kernel_space.c'\" \(324 characters\)
sed "s/^X//" >'kernel_space.c' <<'END_OF_FILE'
X/*
X    Append the following lines at the appropriate place in
X    /etc/conf/pack.d/kernel/space.c
X*/
X
X#ifdef CLED
X/* 	cled ------------- */
X			 cleopen,
X			 cleclose,
X			 cleread,
X			 clewrite,
X			 cleioctl,
X			 cleinput,
X			 cleoutput,
X			 nulldev,
X#endif
X};
X
X#ifdef CLED
Xint     linecnt = 4;
X#else
Xint	linecnt = 3;
X#endif
END_OF_FILE
if test 324 -ne `wc -c <'kernel_space.c'`; then
    echo shar: \"'kernel_space.c'\" unpacked with wrong size!
fi
chmod +x 'kernel_space.c'
# end of 'kernel_space.c'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(41 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#define VERSION "2"
X#define PATCHLEVEL 5
END_OF_FILE
if test 41 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
chmod +x 'patchlevel.h'
# end of 'patchlevel.h'
fi
if test -f 'scled.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scled.c'\"
else
echo shar: Extracting \"'scled.c'\" \(18349 characters\)
sed "s/^X//" >'scled.c' <<'END_OF_FILE'
X/*
X    $Id: scled.c,v 2.5 90/08/26 11:35:26 sw Exp $
X*/
X
X#include <sys/types.h>
X#include <sys/tty.h>
X
X#include <sys/termio.h>
X
X#include <stdio.h>
X#include <ctype.h>
X#include <fcntl.h>
X#include <sys/ioctl.h>
X#include <errno.h>
X
X#include <sys/cledio.h>
X#include <sys/cled.h>
X
Xint			cols = -1;
Xunchar                  *buf;
Xunchar                  inpbuf[256];
Xstruct termio           tio;
Xextern unchar           *malloc(),*getenv();
X
XFILE                    *ifp;
Xint                     cledp;
X
Xunchar                  *cledfn = (unchar *) "/dev/cled";
Xunchar			*empty = (unchar *) "";
X
Xstruct cle_stats        stats;
X
Xstruct items
X{
X    int                     numb;
X    char                    *str;
X};
X
Xstruct items            tcap_seq[] =
X{
X    {TCAP_CLREOL,"clreol"},
X    {TCAP_SETINV,"setinv"},
X    {TCAP_SETNORM,"setnorm"},
X    {TCAP_SAVE,"save"},
X    {TCAP_RESTORE,"restore"},
X    {TCAP_FLASH,"flash"},
X    0
X};
X
Xstruct items            func_names[] =
X{
X    {CLEFUN_INSERT,"insert"},
X    {CLEFUN_INSERT,"overstrike"},
X    {CLEFUN_GOTOBOL,"goto_bol"},
X    {CLEFUN_GOTOEOL,"goto_eol"},
X    {CLEFUN_DELWLFT,"del_word_left"},
X    {CLEFUN_DELWRIT,"del_word_right"},
X    {CLEFUN_DELBOL,"del_to_bol"},
X    {CLEFUN_DELEOL,"del_to_eol"},
X    {CLEFUN_CURSL,"cursor_left"},
X    {CLEFUN_CURSR,"cursor_right"},
X    {CLEFUN_DELCLFT,"del_char_left"},
X    {CLEFUN_DELCRIT,"del_char_right"},
X    {CLEFUN_REFRESH,"refresh"},
X    {CLEFUN_PREVIOUS,"previous"},
X    {CLEFUN_NEXT,"next"},
X    {CLEFUN_FIND,"find"},
X    {CLEFUN_NEWLINE,"newline"},
X    {CLEFUN_ESCAPE,"superquote"},
X    {CLEFUN_NOP,"nop"},
X    {CLEFUN_BELL,"bell"},
X    {CLEFUN_SKIPWR,"skip_word_right"},
X    {CLEFUN_SKIPWL,"skip_word_left"},
X    {CLEFUN_PURGE,"purge"},
X    {CLEFUN_META,"meta"},
X    {CLEFUN_ANSI,"ansi"},
X    {0,0}
X};
X
Xunchar                  *rev_funcnames[CLEFUN_MAX];
Xunchar                  *rev_tcapnames[TCAP_COUNT];
Xunchar                  *set_tcapnames[TCAP_COUNT];
Xchar			*tcap_defs[TCAP_COUNT];
X
Xstruct cle_stats        stats;
Xint                     line = 0,errors = 0;
Xunchar                  delim[] = " \t\n";
Xunchar                  *pathptrs[4];
X
X#define ACC_EXISTS  0
X#define ACC_EXECUTE 1
X#define ACC_WRITE   2
X#define ACC_READ    4
X
X
Xstatic unchar		*rev_keyname(key)
X    int			    key;
X{
X    static unchar		    name[8];
X
X    if (CLEKEY_CHAR(key))
X	    (void) sprintf(name,"M-%c",key);
X    else    (void) sprintf(name,"^%c",(key == 0x7F) ? '?' : key+'@');
X
X    return name;
X}
X
X/*
X   get_pathname is a function that takes as input an array of unchar *'s
X   which are presumed to be path names and a unchar * which is assumed to be
X   a filename. It builds a real filename by gluing each of the path names
X   successively to the filename and doing an access test on the composite
X   name. It returns a pointer to the composite string if the file is
X   accessable otherwise it returns null.
X
X   At entry: paths - ptr to (unchar *) 0 terminated array of unchar pointers each
X   pointing to null terminated pathname string. filename - ptr to filename
X   string amode - access mode which to use to test according to the
X   following: 00 - check for file existance 01 - check for execute (search)
X   02 - check for write 04 - check for read At exit: returns ptr to composite
X   string from malloc'd memory if file accessable else returns NULL.
X*/
X
Xunchar                  *get_pathname(paths,filename,amode)
X    unchar                  **paths,*filename;
X    int                     amode;
X{
X    unchar                  *s;
X    int                     fnlen;
X
X    fnlen = strlen(filename) + 1;
X    if (filename[0] == '/' ||
X	(filename[0] == '.' && filename[1] == '/' ||
X	    (filename[1] == '.' && filename[2] == '/')))
X	paths = (unchar **) 0;
X
X    while (paths != (unchar **) 0 && *paths != (unchar *) 0)
X    {
X	int                     plen;
X
X	plen = strlen(*paths);
X	s = malloc(plen + fnlen);
X	strcpy(s,*paths);
X	strcat(s,filename);
X	if (access(s,amode) == 0)
X	    return s;
X	free(s);
X	++paths;
X    }
X
X    /* check the filename without a path */
X    if (access(filename,amode) == 0)
X    {
X	s = malloc(fnlen);
X	strcpy(s,filename);
X	return s;
X    }
X    return (unchar *) 0;
X}
X
Xint                     show_error(what,token)
X    unchar                  *what,*token;
X{
X    if (token == 0)
X	fprintf(stderr,"Missing %s on line %d\n",what,line);
X    else
X	fprintf(stderr,"Unknown %s {%s} on line %d\n",what,token,line);
X    ++errors;
X}
X
Xunchar                  *outfile = 0;
Xunchar                  *inpfile = 0;
X
X#ifdef NOISY
Xdump_text(ptr,len)
X    unchar                  *ptr;
X    int                     len;
X{
X    int                     i,j;
X    unchar                  *l;
X
X    while (len > 0)
X    {
X	l = ptr;
X	j = (len > 32) ? 32 : len;
X	for (i = 0; i < j; ++i)
X	    fprintf(stderr,"%02X ",*(l + i));
X	fputs("\n",stderr);
X	for (i = 0; i < j; ++i)
X	    fprintf(stderr," %c ",(*(l + i) > ' ') ? *(l + i) : '.');
X	fputs("\n",stderr);
X	ptr += j;
X	len -= j;
X    }
X}
X
X#endif
X
Xvoid                    ioctl_error(old)
X    struct set_key          *old;
X{
X    int                     key,kie,func;
X    unchar                  *kp;
X    struct set_key          *skp;
X
X    skp = (struct set_key *) buf;
X    kp = (unchar *) (skp + 1);
X    kp += skp->kdbuf_len * 2;
X
X    if (old->kdbuf_len != skp->kdbuf_len)
X    {
X	kie = *kp++;
X	func = *kp++;
X	fprintf(stderr,"Error setting Key 0x%02X (%s) to func 0x%02X (%s)\n",
X	    kie,((kie < CLEKEY_MAX) ? rev_keyname(kie) : empty),
X	    func,((func < CLEFUN_MAX) ? rev_funcnames[func] : empty));
X    }
X    else if (old->tcapbuf_len != skp->tcapbuf_len)
X    {
X	int                     i;
X	unchar                  *t,*s;
X
X	i = strlen(kp) + 1;
X	if ((t = (unchar *) malloc(i)) == (unchar *) 0)
X	{
X	    fprintf(stderr,"Cannot get %d bytes reporting tcap_set failure",i);
X	    return;
X	}
X
X	kie = *kp++;
X	for (s = t; i > 0; --i,++kp)
X	    *s++ = (*kp >= ' ' && *kp < 0177) ? *kp : '.';
X	*s = 0;
X	fprintf(stderr,"Error setting string 0x%02X (%s) to \"%s\"\n",
X	    kie,((kie < TCAP_COUNT) ? rev_tcapnames[kie] : empty),t);
X	free(t);
X    }
X    else
X    {
X	fprintf(stderr,"Error %d setting keys/tcap strings in cled\n",errno);
X	fprintf(stderr,"before modes = %08X, kdbuf_len = %d, tcapbuf_len = %d\n",
X	    old->modes,old->kdbuf_len,old->tcapbuf_len);
X	fprintf(stderr,"after  modes = %08X, kdbuf_len = %d, tcapbuf_len = %d\n",
X	    skp->modes,skp->kdbuf_len,skp->tcapbuf_len);
X    }
X}
X
Xvoid                    read_setup()
X{
X    int                     i,anslen = 0;
X    unchar                  *kp,*ap,*abp,*ifn;
X    struct set_key          *skp;
X
X    if (inpfile == (unchar *) 0)
X	inpfile = (unchar *) ".cledrc";
X    pathptrs[0] = (unchar *) "./";
X
X    ap = getenv("CLED");
X    if (ap != (unchar *) 0 && (i = strlen(ap)) > 0)
X    {
X	if (ap[i - 1] != '/')
X	{
X	    kp = malloc(strlen(ap) + 2);
X	    strcpy(kp,ap);
X	    strcat(kp,"/");
X	    ap = kp;
X	}
X    }
X
X    pathptrs[1] = ap;
X    ap = getenv("HOME");
X    if (ap != (unchar *) 0 && (i = strlen(ap)) > 0)
X    {
X	if (ap[i - 1] != '/')
X	{
X	    kp = malloc(strlen(ap) + 2);
X	    strcpy(kp,ap);
X	    strcat(kp,"/");
X	    ap = kp;
X	}
X    }
X
X    pathptrs[2] = ap;
X    ifn = get_pathname(pathptrs,inpfile,ACC_READ);
X    if (ifn == (unchar *) 0)
X    {
X	if (buf != 0)
X	    free(buf);
X	buf = (unchar *) 0;
X	return;
X    }
X
X    ifp = fopen(ifn,"r");
X    if (ifp == 0)
X    {
X	sprintf(inpbuf,"Unable to open input: %s\n\t",ifn);
X	perror(inpbuf);
X	exit(1);
X    }
X
X    tcap_defs[TCAP_CLREOL]	= TCAP_CLREOL_STR;
X    tcap_defs[TCAP_SETINV]	= TCAP_SETINV_STR;
X    tcap_defs[TCAP_SETNORM]	= TCAP_SETNORM_STR;
X    tcap_defs[TCAP_SAVE]	= TCAP_SAVE_STR;
X    tcap_defs[TCAP_RESTORE]	= TCAP_RESTORE_STR;
X    tcap_defs[TCAP_FLASH]	= TCAP_FLASH_STR;
X
X    i = 256 + sizeof (struct set_key) + CLEKEY_MAX * 2;
X    buf = (unchar *) malloc(i * 2);
X    if (buf == 0)
X    {
X	fprintf(stderr,"Unable to allocate %d bytes\n",i);
X	exit(1);
X    }
X
X    skp = (struct set_key *) buf;
X    skp->kdbuf_len = 0;
X    skp->tcapbuf_len = 0;
X    skp->modes = 0;
X
X    kp = (unchar *) (skp + 1);	/* point to key space */
X    abp = ap = kp + CLEKEY_MAX * 2;
X    while (fgets(inpbuf,sizeof (inpbuf),ifp) != NULL)
X    {
X	unchar                  *tok1,*tok2,c;
X	extern unchar           *strtok();
X
X	++line;
X	tok1 = strtok(inpbuf,delim);
X	if (tok1 == 0)
X	    continue;
X
X	if (strcmp(tok1,"columns") == 0)
X	{
X	    tok1 = strtok((unchar *) 0,delim);
X	    if (tok1 == 0)
X	    {
X		show_error("mode",tok1);
X		continue;
X	    }
X
X	    cols = atoi(tok1);
X	    if (cols >= 8 || cols <= MAXLINE)
X		continue;
X
X	    cols = -1;
X
X	    show_error("mode",tok1);
X	    continue;
X	}
X
X	if (strcmp(tok1,"mode") == 0)
X	{
X	    tok1 = strtok((unchar *) 0,delim);
X	    if (tok1 == 0)
X	    {
X		show_error("mode",tok1);
X		continue;
X	    }
X
X	    if (strcmp(tok1,"insert") == 0)
X	    {
X		skp->modes |= CLEMODE_INSERT;
X		continue;
X	    }
X
X	    if (strcmp(tok1,"overstrike") == 0)
X	    {
X		skp->modes |= CLEMODE_OVER;
X		continue;
X	    }
X
X	    show_error("mode",tok1);
X	    continue;
X	}
X
X	if (strcmp(tok1,"key") == 0)
X	{
X	    int                     key,func;
X
X	    tok1 = strtok((unchar *) 0,delim);
X	    if (tok1 == 0)
X	    {
X		show_error("keyname",tok1);
X		continue;
X	    }
X
X	    if (tok1[0] == '^')
X		key = (tok1[1] == '?') ? 0x7F : CLEKEY_CTL(tok1[1]);
X	    else if (tok1[0] == '_')
X		key = CLEKEY_ESC(tok1[1]);
X	    else if (tok1[0] == 'M' && tok1[1] == '-')
X		key = CLEKEY_ESC(tok1[2]);
X	    else
X	    {
X		show_error("keyname",tok1);
X		continue;
X	    }
X
X	    tok1 = strtok((unchar *) 0,delim);
X	    if (tok1 == 0)
X	    {
X		show_error("function name",tok1);
X		continue;
X	    }
X
X	    for (func = 0; func_names[func].numb > 0; ++func)
X		if (strcmp(func_names[func].str,tok1) == 0)
X		    break;
X
X	    if (func_names[func].numb == 0)
X	    {
X		show_error("function name",tok1);
X		continue;
X	    }
X
X	    skp->kdbuf_len += 1;
X	    *kp++ = key;
X	    *kp++ = func_names[func].numb;
X	    continue;
X	}
X
X	if (strcmp(tok1,"string") == 0)
X	{
X	    int                     ans;
X	    unchar                  *s;
X
X	    tok1 = strtok((unchar *) 0,delim);
X	    if (tok1 == 0)
X	    {
X		show_error("string name",tok1);
X		continue;
X	    }
X
X	    for (ans = 0; tcap_seq[ans].str != 0; ++ans)
X		if (strcmp(tcap_seq[ans].str,tok1) == 0)
X		    break;
X
X	    if (tcap_seq[ans].str == 0)
X	    {
X		show_error("string name",tok1);
X		continue;
X	    }
X
X	    tok1 = strtok((unchar *) 0,"\"\r\n");
X	    if (set_tcapnames[ans] != (unchar *) 0)
X	    {
X		anslen -= strlen(set_tcapnames[ans]) - 1;
X		if (anslen < 0)
X		    anslen = 0;
X		free(set_tcapnames[ans]);
X	    }
X
X	    if (tok1 != (unchar *) 0)
X	    {
X		s = (unchar *) set_tcapnames[ans] = malloc(strlen(tok1) + 1);
X		if (s == (unchar *) 0)
X		{
X		    fprintf(stderr,"Unable to allocate %d bytes of mem\n",
X			strlen(tok1) + 1);
X		    exit(1);
X		}
X
X		while (*tok1)
X		{
X		    unchar                  c,*tp;
X
X		    c = *s++ = *tok1++;
X		    if (c == '\\')
X		    {
X			int                     val;
X
X			tp = tok1 - 1;
X			switch ((c = *tok1++))
X			{
X			case 't':	val = '\t';	break;
X			case 'r':	val = '\r';	break;
X			case 'n':	val = '\n';	break;
X			case 'f':	val = '\f';	break;
X			case 'v':	val = '\v';	break;
X
X			case '0':
X			    if (*tok1 < '0' || *tok1 > '7')
X			    {
X				val = 0;
X				fprintf(stderr,"Warning: null in string on line %d\n",line);
X				break;
X			    }
X
X			case '1':
X			case '2':
X			case '3':
X				val = (c - '0') << 6;
X				if (*tok1 < '0' || *tok1 > '7')
X				{
X				    show_error("string constant",tp);
X				    break;
X				}
X				val |= (*tok1++ - '0') << 3;
X				if (*tok1 < '0' || *tok1 > '7')
X				{
X				    show_error("string constant",tp);
X				    break;
X				}
X				val |= *tok1++ - '0';
X				break;
X
X
X			default:
X				val = c;
X			}
X			*(s - 1) = val;
X		    }
X		}
X		*s++ = 0;
X		anslen += s - set_tcapnames[ans];
X	    }
X	    else
X	    {
X		s = set_tcapnames[ans] = malloc(1);
X		if (s == (unchar *) 0)
X		{
X		    fprintf(stderr,"Unable to allocate 1 byte");
X		    exit(1);
X		}
X		*s = 0;
X		anslen += 1;
X	    }
X	    continue;
X	}
X	show_error("keyword",tok1);
X    }
X
X    if (anslen > stats.tcapsize)
X    {
X	fprintf(stderr,"Error: Total length of all strings is greater than %d\n",
X	    stats.tcapsize);
X	exit(1);
X    }
X    if (anslen != 0)
X    {
X	unchar                  *bp;
X
X	bp = buf + sizeof (struct set_key) + skp->kdbuf_len * 2;
X	skp->tcapbuf_len = 0;
X	for (i = 0; i < sizeof (set_tcapnames) / sizeof (unchar *); ++i)
X	{
X	    if (set_tcapnames[i] != (unchar *) 0)
X	    {
X		if (strcmp(tcap_defs[i],set_tcapnames[i]) != 0)
X		{
X		    int                     sln;
X
X		    *bp++ = i;
X		    strcpy(bp,set_tcapnames[i]);
X		    sln = strlen(bp) + 1;
X		    bp += sln;
X		    skp->tcapbuf_len += sln + 1;
X		}
X		free(set_tcapnames[i]);
X		set_tcapnames[i] = (unchar *) 0;
X	    }
X	}
X
X#ifdef NOISY
X	fprintf(stderr,"Found %d bytes of ascii defines:\n",skp->tcapbuf_len);
X	bp = buf + sizeof (struct set_key) + skp->kdbuf_len * 2;
X	dump_text(bp,skp->tcapbuf_len);
X#endif
X    }
X
X#ifdef NOISY
X    fprintf(stderr,"Found modes = %02X, %d key defines, %d bytes of tcap defines and %d errors\n",
X	skp->modes,skp->kdbuf_len,skp->tcapbuf_len,errors);
X#endif
X}
X
Xvoid                    make_output()
X{
X    int                     i;
X    unchar                  *bp,*kp,*ascp;
X    FILE                    *ofp;
X    struct set_key          *kstr;
X
X    ofp = fopen(outfile,"w");
X    if (ofp == 0)
X    {
X	sprintf(inpbuf,"Unable to open %s for write\n\t",outfile);
X	perror(inpbuf);
X	exit(1);
X    }
X
X    if (ioctl(fileno(stderr),LDGETCOLS,&cols) < 0)
X    {
X	perror("error getting # of columns from cled\n\t");
X	exit(1);
X    }
X
X    i = 256 + sizeof (struct set_key) + CLEKEY_MAX * 2;
X    bp = malloc(i);
X    if (ioctl(fileno(stderr),LDGETBF,bp) < 0)
X    {
X	perror("error getting key buf from cled\n\t");
X	exit(1);
X    }
X
X    kstr = (struct set_key *) bp;
X    kp = bp + sizeof (struct set_key);
X    ascp = kp + kstr->kdbuf_len;
X
X#ifdef NOISY
X    fprintf(stderr,"kstr=%08X, kp=%08X, ascp=%08X, key_len=%d, asc_len=%d\n",
X	kstr,kp,ascp,kstr->kdbuf_len,kstr->tcapbuf_len);
X    dump_text(ascp,kstr->tcapbuf_len);
X#endif
X
X    fprintf(ofp,"columns %d\n",cols);
X    fprintf(ofp,"mode %s\n",(kstr->modes & CLEMODE_INSERT) ? "insert" : "overstrike");
X
X    for (i = 0; i < kstr->kdbuf_len; ++i)
X    {
X	int                     func,j;
X
X	func = *kp++;
X	if (func == 0)
X	    continue;
X	if (func >= CLEFUN_MAX)
X	{
X	    fprintf(stderr,"cled returned an unknown function of 0x%02X assigned to key 0x%02X\n",
X		func,i);
X	    continue;
X	}
X	if (i >= CLEKEY_MAX)
X	{
X	    fprintf(stderr,"cled returned unknown key 0x%02X assigned to function %s\n",
X		i,rev_funcnames[func]);
X	    continue;
X	}
X	if (func != CLEFUN_BELL)
X	    fprintf(ofp,"key %s %s\n",rev_keyname(i),rev_funcnames[func]);
X    }
X
X    for (i = 0; i < kstr->tcapbuf_len;)
X    {
X	int                     j;
X
X	j = *ascp++;
X	if (j >= TCAP_COUNT)
X	    fprintf(stderr,"cled returned an unknown tcap_seq of {%s} assigned to 0x%02X\n",
X		ascp,j);
X	else
X	{
X	    unchar                  *b,*s,c;
X
X	    s = inpbuf;
X	    *s = 0;
X	    b = ascp;
X	    while ((c = *b++) != 0)
X	    {
X		if (c < ' ')
X		{
X		    switch (c)
X		    {
X		    case '\t':	strcat(s,"\\t");    break;
X		    case '\r':	strcat(s,"\\r");    break;
X		    case '\n':	strcat(s,"\\n");    break;
X		    case '\f':	strcat(s,"\\f");    break;
X		    case '\v':	strcat(s,"\\v");    break;
X		    default:	sprintf(s,"\\%03o",c);
X		    }
X
X		    s += strlen(s);
X		    continue;
X		}
X		else if (c == '\\')
X		{
X		    *s++ = '\\';
X		    *s++ = '\\';
X		}
X		else
X		    *s++ = c;
X
X		*s = 0;
X	    }
X	    fprintf(ofp,"string %s \"%s\"\n",rev_tcapnames[j],inpbuf);
X	}
X	j = strlen(ascp) + 1;
X	i += j + 1;
X	ascp += j;
X    }
X    fclose(ofp);
X}
X
X#define OPT_OUTPUT 0x01
X#define OPT_ERROR  0x80
X
Xmain(argc,argv)
X    int                     argc;
X    unchar                  **argv;
X{
X    int                     i,opts;
X    unchar                  *kp,*ap,*abp;
X    struct set_key          *skp;
X
X    for (opts = 0,i = 1; i < argc; ++i)
X    {
X	unchar                  *opt;
X
X	opt = argv[i];
X	if (*opt == '-')
X	{
X	    if (i + 1 >= argc)
X	    {
X		opts |= OPT_ERROR;
X		fprintf(stderr,"%s option requires a parameter\n",opt);
X		continue;
X	    }
X	    if (opt[1] == 'o')
X	    {
X		opts |= OPT_OUTPUT;
X		++i;
X		outfile = argv[i];
X		continue;
X	    }
X	    opts |= OPT_ERROR;
X	    continue;
X	}
X	inpfile = argv[i];
X    }
X
X    if ((opts & OPT_ERROR) != 0)
X    {
X	fprintf(stderr,"Usage: %s [-o output_filename] [input_filename]\n",argv[0]);
X	exit(1);
X    }
X
X    for (i = 0; i < CLEFUN_MAX; ++i)
X	rev_funcnames[func_names[i].numb] = (unchar *) func_names[i].str;
X    for (i = 0; i < TCAP_COUNT; ++i)
X	rev_tcapnames[tcap_seq[i].numb] = (unchar *) tcap_seq[i].str;
X
X#ifdef NOISY
X    fprintf(stderr,"stderr fildes = %d. isatty() = %d\n",fileno(stderr),
X	isatty(fileno(stderr)));
X#endif
X
X    if (!isatty(fileno(stderr)))
X    {
X	fprintf(stderr,"stderr is not a tty. Can't set discipline\n");
X	exit(1);
X    }
X
X    if (ioctl(fileno(stderr),TCGETA,&tio) < 0)
X    {
X	perror("Error obtaining termio struct from stderr\n\t");
X	exit(1);
X    }
X
X    cledp = open(cledfn,O_RDWR);
X    if (cledp < 0)
X    {
X	fprintf(stderr,"cled not installed on the system\n");
X	exit(1);
X    }
X
X    if (ioctl(cledp,LDGETS,&stats) < 0)
X    {
X	sprintf(inpbuf,"Error doing LDGETS ioctl to %s\n\t",cledfn);
X	perror(inpbuf);
X	exit(1);
X    }
X    close(cledp);
X
X    if (stats.line == 0)
X    {
X	fprintf(stderr,"cled is not installed as a line discipline\n");
X	exit(1);
X    }
X
X#if 0
X    if (stats.ledbufs <= stats.ledbufs_used ||
X	stats.ttybufs <= stats.ttybufs_used)
X    {
X	fprintf(stderr,"No buffers available. ttybufs free = %d, ledbufs free = %d\n",
X	    stats.ttybufs - stats.ttybufs_used,stats.ledbufs - stats.ledbufs_used);
X	exit(1);
X    }
X#endif
X
X    tio.c_line = stats.line;
X    tio.c_lflag |= CLEDFLAGS;
X    if (ioctl(fileno(stderr),TCSETA,&tio) < 0)
X    {
X	sprintf(inpbuf,"Error setting line discipline to %d\n\t",stats.line);
X	perror(inpbuf);
X	exit(1);
X    }
X
X    if ((opts & OPT_OUTPUT) != 0)
X	make_output();
X
X    read_setup();
X    if (cols > 0)
X	if (ioctl(fileno(stderr),LDSETCOLS,&cols) < 0)
X	{
X	    perror("error setting # of columns in cled\n\t");
X	    fprintf(stderr,"columns %d\n",cols);
X	    exit(1);
X	}
X
X    if (buf != (unchar *) 0)
X    {
X	struct set_key          old;
X
X	old = *(struct set_key *) buf;
X	if (ioctl(fileno(stderr),LDSETBF,buf) < 0)
X	{
X	    perror("error setting key buf in cled\n\t");
X	    ioctl_error(&old);
X	    exit(1);
X	}
X    }
X
X    return 0;
X}
END_OF_FILE
if test 18349 -ne `wc -c <'scled.c'`; then
    echo shar: \"'scled.c'\" unpacked with wrong size!
fi
chmod +x 'scled.c'
# end of 'scled.c'
fi
if test -f 'space.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'space.c'\"
else
echo shar: Extracting \"'space.c'\" \(553 characters\)
sed "s/^X//" >'space.c' <<'END_OF_FILE'
X/*
X    $Id: space.c,v 2.5 90/08/26 11:35:49 sw Exp $
X*/
X
X#include "config.h"
X
X#ifdef CLED
X
X#include "sys/types.h"
X#include "sys/tty.h"
X#include "sys/termio.h"
X#include "sys/cledio.h"
X#include "sys/cled.h"
X
X#if CLED_CNTLS != 1
X#   include "ERROR: cled must have just one controller"
X#endif
X
X#if !MULTI_LB || !defined NCLEPROCS
X#   undef NCLEPROCS
X#   define NCLEPROCS	    1
X#endif
X
Xint		cle_ttys = {CLED_UNITS};
Xint		cle_leds = {CLED_UNITS*NCLEPROCS};
X
Xstruct led_buf   cle_buffers[CLED_UNITS];
Xstruct tty_buf   cle_ttybuf[CLED_UNITS*NCLEPROCS];
X
X#endif
END_OF_FILE
if test 553 -ne `wc -c <'space.c'`; then
    echo shar: \"'space.c'\" unpacked with wrong size!
fi
chmod +x 'space.c'
# end of 'space.c'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

--
Piercarlo "Peter" Grandi           | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcsun!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk

--
Piercarlo "Peter" Grandi           | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcsun!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk