[comp.sources.misc] v08i029: keydef2 - quickly, easily redefine VT[23]xx function keys

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (09/07/89)

Posting-number: Volume 8, Issue 29
Submitted-by: fulvio@oliveb.ATC.Olivetti.Com (Fulvio MARINO)
Archive-name: keydef_fv

On 8 Aug 89 00:05:21 GMT, gordon@prls.UUCP (Gordon Vickers)
submitted to "comp.sources.misc" (posting-number: Volume 7, Issue 55 -
archive-name: keydef) via allbery@uunet.UU.NET (Brandon S. Allbery -
comp.sources.misc) the Subject:
   v07i055: keydef - quickly, easily redefine VT[23]xx function keys

This is my turn.

My keydef program makes the VT[23]xx (and compatibles) key definition
in a different way than the Brandon's.  [Huh?  I just moderate.  ++bsa]
I have NOT encountered the problems that he declared (half of the keys
are not programmable, errors in downloading long definitions, etc.).
This keydef can define the entire set of the user-defined keys; more,
it can clean all the keys, and/or lock all them.
Not X/OPEN (or SysV) users will need to edit one line in keydef.c to
change the #include <string.h> to #include <strings.h>. I don't know
if other changes are requested for the sites that are not X/OPEN.

My English is very bad, but I hope that you will read the manual page,
at least to see all the features.

			Fulvio MARINO (fulvio@oliveb.ATC.Olivetti.Com)
			Olivetti Ivrea, Italy- Sep 4 1989


#! /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 1)."
# Contents:  MANIFEST NOREM README keydef.1u keydef.c keydef.man
#   makefile sample
# Wrapped by fulvio@xmrxos2 on Mon Sep  4 15:57:51 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(501 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X README                     1	Guess!
X MANIFEST                   1	This shipping list
X NOREM			    1	List of precious file (see makefile)
X keydef.1u                  1	Manual page
X keydef.c                   1	The keydef program
X keydef.man                 1	nroff -Tlp -man keydef.1u
X makefile                   1	Make all, install and kit
X sample                     1	A $HOME/.keydef for C-programmers
END_OF_FILE
if test 501 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'NOREM' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'NOREM'\"
else
echo shar: Extracting \"'NOREM'\" \(68 characters\)
sed "s/^X//" >'NOREM' <<'END_OF_FILE'
XMANIFEST
XNOREM
XREADME
Xkeydef.1u
Xkeydef.c
Xkeydef.man
Xmakefile
Xsample
END_OF_FILE
if test 68 -ne `wc -c <'NOREM'`; then
    echo shar: \"'NOREM'\" unpacked with wrong size!
fi
# end of 'NOREM'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(883 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
XOn 8 Aug 89 00:05:21 GMT, gordon@prls.UUCP (Gordon Vickers)
Xsubmitted to "comp.sources.misc" (posting-number: Volume 7, Issue 55 -
Xarchive-name: keydef) via allbery@uunet.UU.NET (Brandon S. Allbery -
Xcomp.sources.misc) the Subject:
X   v07i055: keydef - quickly, easily redefine VT[23]xx function keys
X
XThis is my turn.
X
XMy keydef program makes the VT[23]xx (and compatibles) key definition
Xin a different way than the Brandon's.
XI have NOT encountered the problems that he declared (half of the keys
Xare not programmable, errors in downloading long definitions, etc.).
XThis keydef can define the entire set of the user-defined keys; more,
Xit can clean all the keys, and/or lock all them.
X
XMy English is very bad, but I hope that you will read the manual page,
Xat least to see all the features.
X
X			Fulvio MARINO (fulvio@oliveb.ATC.Olivetti.Com)
X			Olivetti Ivrea, Italy- Sep 4 1989
END_OF_FILE
if test 883 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'keydef.1u' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'keydef.1u'\"
else
echo shar: Extracting \"'keydef.1u'\" \(5314 characters\)
sed "s/^X//" >'keydef.1u' <<'END_OF_FILE'
X.TH KEYDEF local
X.SH NAME
Xkeydef - quickly / easily redefines VT2xx and VT3xx function keys.
X.SH SYNTAX
Xkeydef { [-c] [-l] [keyname1 keyname2 ...] }
X.br
Xkeydef [-f filename [keyname1 keyname2 ...]]
X.SH DESCRIPTION
XThe first sintax specification for the \fIkeydef\fP command is
Xinteractive; at least one flag or a keyname must be specified. For
Xeach \fIkeyname\fP, \fIkeydef\fP asks for its definition. The \fB-c\fP
Xand \fB-l\fP flags have the same meaning, respectively, of
Xthe \fIclear\fP and \fIlock\fP commands used in non-interactive mode
X(see below). Definition follows the same sintax used not interactively.
X.PP
XUsing the 2nd form, \fIkeydef\fP reads its instructions
Xfrom \fIfilename\fP; if \fIfilename\fP is "\fB-\fP", commands are taken
Xfrom standard input, else if it is missing ("\fIkeydef\fP" with no
Xarguments specified), then \fI$HOME/.keydef\fP is read.
X.PP
XCommands in \fIfilename\fP are specified in a shell-like sintax.
XA command is a sequence of non-blank words separated by blanks (a blank
Xis a tab or a space). The first word specifies the name of the command
Xto be executed. Possible commands are \fIclear\fP (to clear all the
Xdefinitions previously set), \fIlock\fP (to lock definitions: i.e.,
Xall the User Defined Keys will be locked after the execution
Xof \fIkeydef\fP -- keys unlock is possible only via Set-Up),
Xor \fIkeyname\fP (to set a definition for \fIkeyname\fP function-key);
X\fIkeyname\fP must be a valid name of a function key, and a
X\fIdefinition\fP follows it.
X.PP
XA word beginning with \fB#\fP causes that word and all the following
Xcharacters up to a new line to be ignored. Explicit null arguments
X(\fB""\fP or \fB''\fP) are retained. A character may be quoted (i.e.,
Xmade to stand for itself) by preceding it with a \fB\\\fP. The
Xpair \fB\\newline\fP is ignored. All characters enclosed between a pair
Xof quote marks (\fB''\fP or \fB""\fP), except the mark itself, are
Xquoted; inside them, \fB\\\fP has no quoting properties.
X.PP
XValid \fIkeynames\fP are \fBF6\fP to \fBF20\f, and \fBS6\fP to \fBS20\fP
X(referenced pressing both the \fBShift\fP and the function key). Some
Xkeys are also referenced by the associated name (ESC, BS, LF, Help, Do).
XType "\fIkeydef -\fP" to print the list of all the possible keynames.
X.PP
XThe (mandatory) argument of a \fIkeyname\fP command is the
X\fIdefinition\fP for that key; inside it, \fB\\\fP and \fB^\fP have a
Xspecial meaning. Certain characters may be represented according to the
Xfollowing table:
X.nf
X
X        CHARACTER       ASCII SYMBOL    ESCAPE SEQUENCE
X
X        newline(NL)          LF              \\n
X        horizontal-tab       HT              \\t
X        vertical-tab         VT              \\v
X        backspace            BS              \\b
X        carriage-return      CR              \\r
X        formfeed             FF              \\f
X        escape               ESC             \\e
X        backslah             \\              \\\\
X        single-quote         '               \\' or \\Q
X        double-quote         "               \\D
X        bit-pattern          ddd             \\ddd
X
X.fi
XThe escape \fB\\ddd\fP consists of the backslash followed by 1, 2, or 3
Xoctal digits, which are taken to specify the value of the desired
Xcharacter. If the character following a backslash is not one of those
Xspecified, the backslash is ignored. \fB^x\fP maps to a control-x for
Xany appropriate x. To program a literal circumflex, preceed it with a
Xbackslash.
X.PP
XA function key is executed by pressing one of the function keys
X(\fBF*\fP), or by pressing SHIFT + function key (\fBS*\fP).
X.SH WARNINGS
XThere is a finite amount of memory in the terminal for storing the
Xdefinitions. The exceeding characters are discharged.
X.PP
XTerminal is getting confused when any character is asynchronously
Xreceived/typed during the execution of \fIkeydef\fP.
X.PP
XDepending on the terminal type and/or setting, not all the keys
Xcan be programmed; typically, F11 (ESC), F12 (BS) and F13 (LF)
Xcan be protected from the user's redefinition.
X.PP
XThis program has been developed and tested on an \fIOlivetti WS 685\fP
Xdesktop video display terminal emulating DEC terminals VT220, VT100 and
XVT52, connected via RS232 to an \fIOlivetti LSX-3010\fP with the \fIL2
XX/OS R2.0\fP Unix System. You should not have porting problems on any
XX/OPEN system.
X.PP
X.SH "SEE ALSO"
XVT220 or VT320 Programmer Pocket Guide, and/or WS 685 User Guide.
X.SH AUTHOR
XFulvio MARINO, Olivetti, Ivrea, Italy (fulvio@oliveb.ATC.Olivetti.Com)
X.PP
XComments, suggestions, and patches welcomed.
X.SH COPYRIGHT
XCopyright (c) 1989 Olivetti S.p.A. Ivrea, Italy.
X.br
XAll rights reserved.
X.PP
XRedistribution and use in source and binary forms are permitted
Xprovided that the above copyright notice and this paragraph are
Xduplicated in all such forms and that any documentation,
Xadvertising materials, and other materials related to such
Xdistribution and use acknowledge that the software was developed
Xby the Olivetti S.p.A., Italy.  The name of Olivetti S.p.A. may
Xnot be used to endorse or promote products derived from this
Xsoftware without specific prior written permission.
X.br
XTHIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
XIMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
XWARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
END_OF_FILE
if test 5314 -ne `wc -c <'keydef.1u'`; then
    echo shar: \"'keydef.1u'\" unpacked with wrong size!
fi
# end of 'keydef.1u'
fi
if test -f 'keydef.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'keydef.c'\"
else
echo shar: Extracting \"'keydef.c'\" \(13595 characters\)
sed "s/^X//" >'keydef.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1989 Olivetti S.p.A. Ivrea, Italy.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the Olivetti S.p.A. Ivrea, Italy.  The name of Olivetti may
X * not be used to endorse or promote products derived from this
X * software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X/*
X * keydef() - easily / quickly redefine vt200, vt300 function keys
X *
X *		(Fulvio MARINO - Sep 4, 1989)
X */
X
X
X#if defined(lint) && defined(m68k)
Xchar *strdup(a,b) char *a, *b; { return (a?a:b); }
X#endif lint
X
X
X#include <stdio.h>
X#include <string.h>
X#include <sys/types.h>
X#include <sys/param.h>
X
X
Xextern void	perror();
Xextern char	*getenv(), *malloc(), *realloc();
X
X
X#define Fprintf	(void)fprintf
X
X#define	ctrl(ch)	((ch) & 037)
X
X#define ESC	ctrl('[')
X#define BSe	ESC
X#define BSn	'\n'
X#define BSt	'\t'
X#define BSv	'\v'
X#define BSb	'\b'
X#define BSr	'\r'
X#define BSf	'\f'
X#define BSbs	'\\'
X#define BSq	'\''
X#define BSdq	'"'
X
X
X/*
X * Error codes and messages
X */
X
Xstatic int	Err_No = 0;
X
Xstatic char	*ErrTable[] = {
X	"",
X#define E_INT		1
X	"Internal error",
X#define E_INV_KN	2
X	"Invalid key name",
X#define E_INV_SN	3
X	"Invalid string definition",
X#define E_SINTAXERR	4
X	"Sintax error",
X#define E_INVCMD	5
X	"Invalid command",
X#define E_INVARG	6
X	"Invalid argument",
X#define E_KEXP		7
X	"Key value expected",
X#define E_TOO		8
X	"Too many args for command",
X#define E_NOSPC		9
X	"Not enough space",
X#define E_INV_CH	10
X	"Value do not fit in a character"
X};
X
X
X/*
X * Pclr values:
X *	'1'	Clear only the key(s) being programmed
X *	not '1'	Clear all keys before programming
X */
X
X#define K_NOCLR		'1'
X#define K_CLRALL	'0'
X
Xstatic u_char	Pclr = K_NOCLR;
X
X
X/*
X * Plk denotes whether or not to lock keys against redefinition:
X *	'1'	Do not lock
X *	'0'	Lock
X */
X
X#define K_NOLCK		'1'
X#define K_LCK		'0'
X
Xstatic u_char	Plk = K_NOLCK;
X
X
X/*
X * Kn: denotes the function key to be programmed; next table is mapping
X * each key name on its function number.
X */
X
Xtypedef struct {
X		char	*Key;	/* Key name */
X		u_char	Fn;	/* Function number */
X} t_table;
X
Xstatic t_table	Table[] = {
X	{ "F6",   1 }, { "F7",   2 }, { "F8",   3 },
X	{ "F9",   4 }, { "F10",  5 }, { "F11",  6 },
X	{ "F12",  7 }, { "F13",  8 }, { "F14",  9 },
X	{ "F15", 10 }, { "F16", 11 }, { "F17", 12 },
X	{ "F18", 13 }, { "F19", 14 }, { "F20", 15 },
X	{ "S6",  17 }, { "S7",  18 }, { "S8",  19 },
X	{ "S9",  20 }, { "S10", 21 }, { "S11", 23 },
X	{ "S12", 24 }, { "S13", 25 }, { "S14", 26 },
X	{ "S15", 28 }, { "S16", 29 }, { "S17", 31 },
X	{ "S18", 32 }, { "S19", 33 }, { "S20", 34 },
X	/* Next items to allow multiple names for some key */
X	{ "F-ESC", 6 }, { "F-BS", 7 }, { "F-LF", 8 },
X	{ "F-Help", 10 }, { "F-Do", 11 },
X	{ "S-ESC", 23 }, { "S-BS", 24 }, { "S-LF", 25 },
X	{ "S-Help", 28 }, { "S-Do", 29 }
X};
X
X#define Tsize	(sizeof(Table) / sizeof(Table[0]))
X
Xstatic u_char	Kt[Tsize];
X
X
X/*
X * GetKn(Fn)
X *	returns the function number of a given key name Fn;
X *	on error, 0 is returned and Err_No is set.
X */
X
Xstatic u_char
XGetKn(Fn)
Xchar	*Fn;
X{
X	int	i = 0;
X
X	if (Fn) {
X		do {
X			if (! strcmp(Fn, Table[i].Key))
X				return(Table[i].Fn);
X		} while (++i < Tsize);
X	}
X
X	Err_No = E_INV_KN;
X	return((u_char)0);
X}
X
X
Xstatic char	*Tokbuf = NULL;
Xstatic unsigned	Toksize = 0;
X
Xstatic u_char	*UDKbuf = (u_char)NULL;
Xstatic unsigned	UDKsize = 0;
X
X
X/*
X * Prepare_DECUDK(kinfo)
X *	prepares in UDKbuf the DECUDK sequence, the format of which is
X *		DCS Pclr ; Plk | K1 / S1 ; K2 / S2 ; ... ; Kn / Sn ST
X *	(kinfo)(&Kn, &Str) is called to get the function number (in Kn)
X *	and the programming string (in Str); (kinfo) returns 0 on end,
X *	-1 (+ Err_No set) on error, or a positive value if ok.
X *	Backslashes in UDKbuf are interpreted as the Green Hills
X *	C-compiler does.
X *	The number of character(s) in UDKbuf is returned on success,
X *	else -1.
X */
X
Xstatic int
XPrepare_DECUDK(kinfo)
Xint	(*kinfo)();
X{
X	int		n, t;
X	u_char		Kn;
X	u_char		*Str, c;
X	u_int		d;
X
X	if (! UDKsize
X	   && (UDKbuf = (u_char *)malloc(UDKsize = BUFSIZ)) == NULL) {
X		Err_No = E_NOSPC;
X		return -1;
X	}
X	UDKbuf[0] = ESC,  UDKbuf[1] = 'P';	/* DCS */
X	UDKbuf[3] = ';';			/* Pclr ender */
X	UDKbuf[5] = '|';			/* Plk ender */
X	n = 6;					/* Start of Kn/Sn seq */
X
X	while ((t = (kinfo)(&Kn, &Str)) > 0) {
X		if (!Kn)
X			continue;
X		/* Verify if Kn is in the selected key set */
X		for (d = 0; d < Tsize; d++)
X			if (Kn == Kt[d])
X				break;
X		if (d >= Tsize)
X			continue;
X
X		if (! Str) {
X			Err_No = E_INT;
X			return (-1);
X		}
X
X		/* Kn */
X		if (Kn > 9)
X			UDKbuf[n++] = (Kn / 10) + '0';
X		UDKbuf[n++] = (Kn % 10) + '0';
X		UDKbuf[n++] = '/';
X
X		/* Sn */
X		t = 0;
X		while (c = *Str++) {
X			if (n > (UDKsize - 10) && (UDKbuf =
X			   (u_char *)realloc((char *)UDKbuf,
X			   UDKsize += BUFSIZ)) == NULL) {
X				Err_No = E_NOSPC;
X				return -1;
X			}
X			if (c == '^') {
X				if (! (c = *Str++)) {
X					Err_No = E_INV_SN;
X					return (-1);
X				}
X				c = ctrl(c);
X			} else if (c == '\\') {
X				if (! (c = *Str++)) {
X					Err_No = E_INV_SN;
X					return (-1);
X				}
X				switch (c) {
X				case '\'':
X				case 'Q':	c = BSq; break;
X				case '\\':	c = BSbs; break;
X				case 'D':	c = BSdq; break;
X				case 'b':	c = BSb; break;
X				case 'e':	c = BSe; break;
X				case 'f':	c = BSf; break;
X				case 'n':	c = BSn; break;
X				case 'r':	c = BSr; break;
X				case 't':	c = BSt; break;
X				case 'v':	c = BSv; break;
X				default:
X/*----------------------------- FOLDING ------------------------------*/
X	if (c < '0' || c > '7')
X		break;
X	d = 0;
X	for (t = 0; t++ < 3; ) {
X		if ((d = 8 * d + (u_int)c - '0') > (u_int)((u_char)~0)) {
X			Err_No = E_INV_CH;
X			return -1;
X		}
X		c = *Str++;
X		if (c < '0' || c > '7')
X			break;
X	}
X	Str--;
X	c = (u_char)d;
X/*---------------------------- UNFOLDING -----------------------------*/
X				}
X			}
X			UDKbuf[n] = c / 16;
X			UDKbuf[n] += UDKbuf[n] > 9 ? 'a' - 10 : '0';
X			UDKbuf[++n] = c % 16;
X			UDKbuf[n] += UDKbuf[n] > 9 ? 'a' - 10 : '0';
X			n++;
X		}
X		UDKbuf[n++] = ';';
X	}
X
X	if (t < 0) {
X		return (-1);
X	}
X
X	UDKbuf[2] = Pclr;			/* Pclr value */
X	UDKbuf[4] = Plk;			/* Plk value */
X	UDKbuf[n] = ESC, UDKbuf[++n] = '\\';	/* ST */
X
X	return(n + 1);
X}
X
X
X/*
X * Line Parsing
X */
X
Xstatic int	lineno = 0;
Xstatic FILE	*input = (FILE *)NULL;
X
X/*
X * Get_Char()
X *	gets a character from `input' (must be set correctly!);
X *	the global lineno keeps trace of input.
X */
X
Xstatic int
XGet_Char()
X{
X	static int	c = 0;
X
X	switch (c = c == EOF ? EOF : getc(input)) {
X	case '\n':	lineno++; break;
X	case EOF:	return(-1);
X	}
X	return(c);
X	
X}
X
X#define G_EOF		-1
X#define G_NULLTOK	-2
X#define G_SINTAXERR	-3
X
X/*
X * Get_Token(o)
X *	scans input for next token (command, argument, ...), and writes
X *	it in Tokbuf, starting at offset o; input sintax is like in
X #	/bin/sh (it uses ", ', #, backslashes, and multi-line);
X *	it returns the characters written in buf (>0),
X *	or 0		if no token found in line
X *	or G_EOF	on end-of-file detection
X *	or G_NULLTOK	if there is a null token ('' or "")
X *	or G_SINTAXERR	on a sintax error (in this case the global
X *			Err_No is set)
X */
X
Xstatic int
XGet_Token(o)
Xint	o;
X{
X	static int	oc = 0;
X	int	c, got = 0, inside = 0, n = o, takenext = 0;
X
X	if (oc == '\n')
X		return (oc = 0);
X
X	for ( ; ; ) {
X		if (n >= Toksize &&
X		   (Tokbuf = Toksize
X		    ? realloc(Tokbuf, Toksize += BUFSIZ)
X		    : malloc(Toksize = BUFSIZ)
X		   ) == NULL) {
X			Err_No = E_NOSPC;
X			return G_SINTAXERR;
X		}
X		c = Get_Char();
X		if (takenext) {
X			if (c == -1) {
X				Err_No = E_SINTAXERR;
X				return(G_SINTAXERR);
X			}
X			if (c != '\n')
X				Tokbuf[n++] = (u_char)c;
X			takenext = 0;
X			continue;
X		}
X		if (c == '\\' && ! inside) {
X			takenext = 1;
X			continue;
X		}
X		if (c == '"' || c == '\'') {
X			if (c == inside) {
X				got = G_NULLTOK;
X				inside = 0;
X				continue;
X			} else if (!inside) {
X				inside = c;
X				continue;
X			}
X		}
X		if (inside) {
X			Tokbuf[n++] = (u_char)c;
X			continue;
X		}
X		if (c == '#')
X			while (c = Get_Char())
X				if (c == '\n')
X					break;
X		if ((c == ' ' || c == '\t') && ((n - o) || got)
X		    || c == '\n' || c == -1) {
X			Tokbuf[n] = '\0';
X			n -= o;
X			oc = c;
X			return (n ? n : (got ? got : (c == -1 ? G_EOF : 0)));
X		}
X		if (c != ' ' && c != '\t')
X			Tokbuf[n++] = (u_char)c;
X	}
X
X	/* NOTREACHED */
X
X}
X
X
Xstatic int
XFromFile(Key, Str)
Xu_char	*Key;
Xchar	**Str;
X{
X	int	n;
X
X	for ( ; ; ) {
X		switch (n = Get_Token(0)) {
X		case 0:			continue;	/* next line */
X		case G_EOF:		return 0;	/* data end */
X		case G_SINTAXERR:	return -1;	/* error */
X		case G_NULLTOK:		break;		/* null token */
X		default:		if (n < 0) {
X						/* internal error */
X						Err_No = E_INT;
X						return -1;
X					}
X		}
X		break;
X	}
X
X	n = -1;
X
X	/*
X	 * Validate object token
X	 */
X	*Key = 0;
X	if (!strcmp(Tokbuf, "clear"))
X		Pclr = K_CLRALL, Tokbuf[0] = '\0';
X	else if (!strcmp(Tokbuf, "lock"))
X		Plk = K_LCK, Tokbuf[0] = '\0';
X	else if ((*Key = GetKn(Tokbuf)) == 0) {
X		Err_No = E_INV_KN;
X		return -1;
X	} else {
X		/*
X		 * Get key arg
X		 */
X		switch (n = Get_Token(0)) {
X		case G_EOF:
X		case 0:			Err_No = E_KEXP;	/* set how ? */
X		case G_SINTAXERR:
X					return -1;
X		case G_NULLTOK:		n = 0;
X					Tokbuf[0] = '\0';
X					break;		/* null token */
X		default:		if (n < 0) {
X						/* internal error */
X						Err_No = E_INT;
X						return -1;
X					}
X		}
X	}
X
X	/*
X	 * No more arguments expected
X	 */
X	switch (n = Get_Token(n+1)) {
X	case G_EOF:
X	case 0:			break;		/* eof/eol are right */
X	case G_SINTAXERR:	return -1;	/* error */
X	case G_NULLTOK:		n = 0;		/* null token */
X	default:		if (n < 0) {
X					/* internal error */
X					Err_No = E_INT;
X				} else
X					Err_No = E_TOO;
X				return -1;
X	}
X
X	*Str = Tokbuf;
X
X	return 1;
X}
X
X
Xstatic int
XFromTty(Key, Str)
Xu_char	*Key;
Xchar	**Str;
X{
X	static int	ind = 0;
X	int	i, k;
X
X	if ((*Key = k = Kt[ind++]) == 0)
X		return 0;
X
X	for (i = 0; k != Table[i].Fn; i++)
X		;
X	Fprintf(stderr, "Key \"%s\"", Table[i].Key);
X	while(++i < Tsize) {
X		if (k == Table[i].Fn) {
X			Fprintf(stderr, "==\"%s\"", Table[i].Key);
X		}
X	}
X	Fprintf(stderr, ": ");
X	(void)fflush(stderr);
X
X	/*
X	 * Get key arg
X	 */
X	switch (i = Get_Token(0)) {
X	case G_EOF:
X	case 0:			Err_No = E_KEXP;	/* set how ? */
X	case G_SINTAXERR:
X				return -1;
X	case G_NULLTOK:		i = 0;
X				Tokbuf[0] = '\0';
X				break;		/* null token */
X	default:		if (i < 0) {
X					/* internal error */
X					Err_No = E_INT;
X					return -1;
X				}
X	}
X
X	/*
X	 * No more arguments expected
X	 */
X	switch (i = Get_Token(i+1)) {
X	case G_EOF:
X	case 0:			break;		/* eof/eol are right */
X	case G_SINTAXERR:	return -1;	/* error */
X	case G_NULLTOK:		i = 0;		/* null token */
X	default:		if (i < 0) {
X					/* internal error */
X					Err_No = E_INT;
X				} else
X					Err_No = E_TOO;
X				return -1;
X	}
X
X	*Str = Tokbuf;
X
X	return 1;
X}
X
X
Xstatic void
Xusage()
X{
X	Fprintf(stderr, "\
XUsage: keydef [-f {filename|-}] [--] [keyname ...]\n\
X       keydef [-c] [-l] keyname ...\n\
X       keydef -{c|l} [keyname ...]\n");
X
X}
X
X
X/*
X *	MAIN
X */
X
X#define KEYRC "/.keydef"
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	extern int	getopt(), optind, opterr;
X	extern char	*optarg;
X	int		c, errflg, fflg, cflg, lflg;
X	char		*ifile, *p;
X	u_char		Kn;
X	int		(*kinfo)();
X
X	opterr = 0;
X	errflg = fflg = cflg = lflg = 0;
X
X	if (argc > 1) {
X
X		while ((c = getopt(argc, argv, "f:cl")) != EOF)
X			switch(c) {
X			case 'f':
X				if ( fflg++ || cflg || lflg || ! optarg)
X					errflg = 1;
X				else
X					ifile = optarg;
X				break;
X			case 'c':
X				if (cflg++ || fflg)
X					errflg = 1;
X				else
X					Pclr = K_CLRALL;
X				break;
X			case 'l':
X				if (lflg++ || fflg)
X					errflg = 1;
X				else
X					Plk = K_LCK;
X				break;
X			case '?':
X				errflg = 1;
X				break;
X			}
X	
X	
X		if (errflg) {
X			usage();
X			return 1;
X		}
X	
X	} else {
X
X		if ((p = getenv("HOME")) == NULL) {
X			Fprintf(stderr, "\"$HOME\" not found.\n");
X			return 1;
X		}
X		if ((ifile = malloc((unsigned)(strlen(p)
X		    + sizeof(KEYRC)))) == NULL) {
X			Fprintf(stderr, "malloc error.\n");
X			return 1;
X		}
X		(void)strcpy(ifile, p);
X		(void)strcat(ifile, KEYRC);
X
X		fflg = optind = 1;
X
X	}
X
X	for (c = 0; optind < argc; ) {
X		p = argv[optind++];
X		if ((Kn = GetKn(p)) == 0) {
X			Fprintf(stderr, "\"%s\": bad key name.\n", p);
X			Fprintf(stderr, "Available key names are:\n\t", p);
X			c = 0;
X			for ( ; ; ) {
X				Fprintf(stderr, "%s ", Table[c++].Key);
X				if (c == Tsize) {
X					(void)putc('\n', stderr);
X					break;
X				}
X				if (!(c % 5))
X					(void)putc('\n', stderr);
X				(void)putc('\t', stderr);
X			}
X			return 1;
X		}
X		errflg = c; /* using errflg as temp */
X		while(errflg-- > 0)
X			if (Kt[errflg] == Kn)
X				break;
X		if (errflg < 0)	/* Not already selected */
X			Kt[c++] = Kn;
X	}
X	if (! (Kn = c) && fflg) /* If no key args, select all keys */
X		for (c = 0; c < Tsize; c++)
X			Kt[c] = Table[c].Fn;
X
X	if (fflg) {
X		if (strcmp(ifile, "-")
X		    && (input = freopen (ifile, "r", stdin)) == NULL) {
X			perror(ifile);
X			return(1);
X		} else
X			input = stdin;
X		kinfo = FromFile;
X	} else {
X		input = stdin;
X		kinfo = FromTty;
X	}
X
X	if ((c = Prepare_DECUDK(kinfo)) > 0
X	    && write(fileno(stdout), (char *)UDKbuf, (unsigned)c) != c) {
X		perror("output error");
X		return 1;
X	} else if (c < 0) {
X		(void)Fprintf(stderr, "line %d: %s.\n", lineno, ErrTable[Err_No]);
X		return 1;
X	}
X
X#if defined(lint) && defined(m68k)
X	return((int)strdup(NULL,NULL));
X#else
X	return 0;
X#endif lint
X}
END_OF_FILE
if test 13595 -ne `wc -c <'keydef.c'`; then
    echo shar: \"'keydef.c'\" unpacked with wrong size!
fi
# end of 'keydef.c'
fi
if test -f 'keydef.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'keydef.man'\"
else
echo shar: Extracting \"'keydef.man'\" \(8947 characters\)
sed "s/^X//" >'keydef.man' <<'END_OF_FILE'
X
X
X
X     KKKKEEEEYYYYDDDDEEEEFFFF((((llllooooccccaaaallll))))               UUUUNNNNIIIIXXXX 5555....0000                KKKKEEEEYYYYDDDDEEEEFFFF((((llllooooccccaaaallll))))
X
X
X
X     NNNNAAAAMMMMEEEE
X          keydef - quickly / easily redefines VT2xx and VT3xx function
X          keys.
X
X     SSSSYYYYNNNNTTTTAAAAXXXX
X          keydef { [-c] [-l] [keyname1 keyname2 ...] }
X          keydef [-f filename [keyname1 keyname2 ...]]
X
X     DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
X          The first sintax specification for the _k_e_y_d_e_f command is
X          interactive; at least one flag or a keyname must be
X          specified. For each _k_e_y_n_a_m_e, _k_e_y_d_e_f asks for its definition.
X          The ----cccc and ----llll flags have the same meaning, respectively, of
X          the _c_l_e_a_r and _l_o_c_k commands used in non-interactive mode
X          (see below). Definition follows the same sintax used not
X          interactively.
X
X          Using the 2nd form, _k_e_y_d_e_f reads its instructions from
X          _f_i_l_e_n_a_m_e; if _f_i_l_e_n_a_m_e is "----", commands are taken from
X          standard input, else if it is missing ("_k_e_y_d_e_f" with no
X          arguments specified), then $_H_O_M_E/._k_e_y_d_e_f is read.
X
X          Commands in _f_i_l_e_n_a_m_e are specified in a shell-like sintax.
X          A command is a sequence of non-blank words separated by
X          blanks (a blank is a tab or a space). The first word
X          specifies the name of the command to be executed. Possible
X          commands are _c_l_e_a_r (to clear all the definitions previously
X          set), _l_o_c_k (to lock definitions: i.e., all the User Defined
X          Keys will be locked after the execution of _k_e_y_d_e_f -- keys
X          unlock is possible only via Set-Up), or _k_e_y_n_a_m_e (to set a
X          definition for _k_e_y_n_a_m_e function-key); _k_e_y_n_a_m_e must be a
X          valid name of a function key, and a _d_e_f_i_n_i_t_i_o_n follows it.
X
X          A word beginning with #### causes that word and all the
X          following characters up to a new line to be ignored.
X          Explicit null arguments ("""""""" or '''''''') are retained. A character
X          may be quoted (i.e., made to stand for itself) by preceding
X          it with a \\\\. The pair \\\\nnnneeeewwwwlllliiiinnnneeee is ignored. All characters
X          enclosed between a pair of quote marks ('''''''' or """"""""), except
X          the mark itself, are quoted; inside them, \\\\ has no quoting
X          properties.
X
X          Valid _k_e_y_n_a_m_e_s are FFFF6666 to FFFF22220000 aaaannnndddd SSSS6666 ttttoooo SSSS22220000 ((((rrrreeeeffffeeeerrrreeeennnncccceeeedddd
X          pppprrrreeeessssssssiiiinnnngggg bbbbooootttthhhh tttthhhheeee SSSShhhhiiiifffftttt aaaannnndddd tttthhhheeee ffffuuuunnnnccccttttiiiioooonnnn kkkkeeeeyyyy)))).... SSSSoooommmmeeee kkkkeeeeyyyyssss aaaarrrreeee
X          aaaallllssssoooo rrrreeeeffffeeeerrrreeeennnncccceeeedddd bbbbyyyy tttthhhheeee aaaassssssssoooocccciiiiaaaatttteeeedddd nnnnaaaammmmeeee ((((EEEESSSSCCCC,,,, BBBBSSSS,,,, LLLLFFFF,,,, HHHHeeeellllpppp,,,,
X          DDDDoooo))))....  TTTTyyyyppppeeee """"_k_e_y_d_e_f -"""" ttttoooo pppprrrriiiinnnntttt tttthhhheeee lllliiiisssstttt ooooffff aaaallllllll tttthhhheeee ppppoooossssssssiiiibbbblllleeee
X          kkkkeeeeyyyynnnnaaaammmmeeeessss....
X
X          The (mandatory) argument of a _k_e_y_n_a_m_e command is the
X          _d_e_f_i_n_i_t_i_o_n for that key; inside it, \\\\ and ^^^^ have a special
X          meaning. Certain characters may be represented according to
X          the following table:
X
X
X
X     Page 1                                           (printed 9/4/89)
X
X
X
X
X
X
X     KKKKEEEEYYYYDDDDEEEEFFFF((((llllooooccccaaaallll))))               UUUUNNNNIIIIXXXX 5555....0000                KKKKEEEEYYYYDDDDEEEEFFFF((((llllooooccccaaaallll))))
X
X
X
X                  CHARACTER       ASCII SYMBOL    ESCAPE SEQUENCE
X
X                  newline(NL)          LF              \n
X                  horizontal-tab       HT              \t
X                  vertical-tab         VT              \v
X                  backspace            BS              \b
X                  carriage-return      CR              \r
X                  formfeed             FF              \f
X                  escape               ESC             \e
X                  backslah             \               \\
X                  single-quote         '               \' or \Q
X                  double-quote         "               \D
X                  bit-pattern          ddd             \ddd
X
X          The escape \\\\dddddddddddd consists of the backslash followed by 1, 2,
X          or 3 octal digits, which are taken to specify the value of
X          the desired character. If the character following a
X          backslash is not one of those specified, the backslash is
X          ignored. ^^^^xxxx maps to a control-x for any appropriate x. To
X          program a literal circumflex, preceed it with a backslash.
X
X          A function key is executed by pressing one of the function
X          keys (FFFF****), or by pressing SHIFT + function key (SSSS****).
X
X     WWWWAAAARRRRNNNNIIIINNNNGGGGSSSS
X          There is a finite amount of memory in the terminal for
X          storing the definitions. The exceeding characters are
X          discharged.
X
X          Terminal is getting confused when any character is
X          asynchronously received/typed during the execution of
X          _k_e_y_d_e_f.
X
X          Depending on the terminal type and/or setting, not all the
X          keys can be programmed; typically, F11 (ESC), F12 (BS) and
X          F13 (LF) can be protected from the user's redefinition.
X
X          This program has been developed and tested on an _O_l_i_v_e_t_t_i _W_S
X          _6_8_5 desktop video display terminal emulating DEC terminals
X          VT220, VT100 and VT52, connected via RS232 to an _O_l_i_v_e_t_t_i
X          _L_S_X-_3_0_1_0 with the _L_2 _X/_O_S _R_2._0 Unix System. You should not
X          have porting problems on any X/OPEN system.
X
X     SSSSEEEEEEEE AAAALLLLSSSSOOOO
X          VT220 or VT320 Programmer Pocket Guide, and/or WS 685 User
X          Guide.
X
X     AAAAUUUUTTTTHHHHOOOORRRR
X          Fulvio MARINO, Olivetti, Ivrea, Italy
X          (fulvio@oliveb.ATC.Olivetti.Com)
X
X          Comments, suggestions, and patches welcomed.
X
X
X
X     Page 2                                           (printed 9/4/89)
X
X
X
X
X
X
X     KKKKEEEEYYYYDDDDEEEEFFFF((((llllooooccccaaaallll))))               UUUUNNNNIIIIXXXX 5555....0000                KKKKEEEEYYYYDDDDEEEEFFFF((((llllooooccccaaaallll))))
X
X
X
X     CCCCOOOOPPPPYYYYRRRRIIIIGGGGHHHHTTTT
X          Copyright (c) 1989 Olivetti S.p.A. Ivrea, Italy.
X          All rights reserved.
X
X          Redistribution and use in source and binary forms are
X          permitted provided that the above copyright notice and this
X          paragraph are duplicated in all such forms and that any
X          documentation, advertising materials, and other materials
X          related to such distribution and use acknowledge that the
X          software was developed by the Olivetti S.p.A., Italy.  The
X          name of Olivetti S.p.A. may not be used to endorse or
X          promote products derived from this software without specific
X          prior written permission.
X          THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS
X          OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
X          IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A
X          PARTICULAR PURPOSE.
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X     Page 3                                           (printed 9/4/89)
X
X
X
END_OF_FILE
echo shar: 1273 control characters may be missing from \"'keydef.man'\"
if test 8947 -ne `wc -c <'keydef.man'`; then
    echo shar: \"'keydef.man'\" unpacked with wrong size!
fi
# end of 'keydef.man'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(1430 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
X
X########################################################################
X#
X# Copyright (c) 1989 Olivetti S.p.A. Ivrea, Italy.
X# All rights reserved.
X#
X# Redistribution and use in source and binary forms are permitted
X# provided that the above copyright notice and this paragraph are
X# duplicated in all such forms and that any documentation,
X# advertising materials, and other materials related to such
X# distribution and use acknowledge that the software was developed
X# by the Olivetti S.p.A. Ivrea, Italy.  The name of Olivetti may
X# not be used to endorse or promote products derived from this
X# software without specific prior written permission.
X# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X#
X########################################################################
X
XSHELL=/bin/sh
X
XBINDIR=/usr/local/bin
XMANDIR=/usr/local/man
X
XBIN=$(BINDIR)/keydef
XMAN=$(MANDIR)/keydef.1
X
X
Xall install:: keydef	# Use built-in rules
X
Xinstall:: # For super-user only
X	cp keydef $(BIN)
X	cp keydef.1u $(MAN)
X
Xclean: NOREM	# rm all files not specified in NOREM
X	@- a="`ls . | fgrep -vx -f NOREM`" \
X		|| exit 0 \
X		&& echo rm -rf $$a \
X		&& rm -rf $$a
X
Xkeydef.man: keydef.1u
X	nroff -Tlp -man $? > $@
X
XMANIFEST: NOREM
X	makekit -m `cat $@`
X
Xkit: keydef.man MANIFEST
X	makekit -i MANIFEST -h 2
END_OF_FILE
if test 1430 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'sample' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sample'\"
else
echo shar: Extracting \"'sample'\" \(3610 characters\)
sed "s/^X//" >'sample' <<'END_OF_FILE'
X########################################################################
X#
X# Copyright (c) 1989 Olivetti S.p.A. Ivrea, Italy.
X# All rights reserved.
X#
X# Redistribution and use in source and binary forms are permitted
X# provided that the above copyright notice and this paragraph are
X# duplicated in all such forms and that any documentation,
X# advertising materials, and other materials related to such
X# distribution and use acknowledge that the software was developed
X# by the Olivetti S.p.A. Ivrea, Italy.  The name of Olivetti may
X# not be used to endorse or promote products derived from this
X# software without specific prior written permission.
X# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X#
X########################################################################
X
X
Xclear	# erase the contents of all the f-keys.
X
X#lock	# after the settings here specified, disable key definitions
X	# (enabling can be done only via Set-Up)
X
X# The following f-keys can be redefined only if your terminal setting
X# allows this.
XF-ESC	\\e
XF-BS	\\b
XF-LF	\\n
X
XS11	\\e	# Function key S11 may default to 'esc' but you can
X		# override it here
XS12	\\b
XS13	\\n
X
X#
X# Set my C-lang `vi-environment'
X#
X
XF6 \
X"Qset ai eb ic nomesg nu opt para= prompt redraw noremap"\
X" report=1 sections= shell=/bin/sh sm smd tl=0 tags=tags terse"\
X" timeout noremap
Xmap! #/ /*^V\r * ^V\r*/^V^[kA
Xmap! #in #include <>^V^[i
Xmap! #de #define \t/*  */^V^[0f a
Xmap! #un #undef\t
Xmap! #id #ifdef 
Xmap! #if #if defined()^V^[i
Xmap! #el #else
Xmap! #en #endif
Xmap! br' break;
Xmap! ca' case : /*  */^V\r\tbreak;^V^[k0f:i
Xmap! ch' char\t;^V^[i
Xmap! co' continue;
Xmap! de' default: /*  */^V\r\tbreak;^V^[O
Xmap! do' double\t;^V^[i
Xmap! dw' do {^V\r} while();^V^[O\t
Xmap! ei' else if () {^V\r}^V^[k0f(a
Xmap! el' else {^V\r}^V^[O\t
Xmap! en' enum {^V\r};^V^[O\t
Xmap! ex' extern ;^V^[i
Xmap! fl' float ;^V^[i
Xmap! fo' for (;;) {^V\r}^V^[k0f(a
Xmap! go' goto ;^V^[i
Xmap! if' if () {^V\r}^V^[k0f(a
Xmap! in' int\t;^V^[i
Xmap! lo' long\t;^V^[i
Xmap! ma' main(argc, argv, environ)^V\rint\targc;^V\rchar\t*argv[], *environ[];^V\r{^V\r}^V^[O\t
Xmap! re' return();^V^[hi
Xmap! rg' register ;^V^[i
Xmap! sc' static ;^V^[i
Xmap! sh' short ;^V^[i
Xmap! si' sizeof()^V^[i
Xmap! st' struct {^V\r};^V^[k0f a
Xmap! sw' switch () {^V\rcase : /* */^V\r\tbreak;^V\r ^V^[xr}kkk0f(a
Xmap! ty' typedef ;^V^[i
Xmap! un' union {^V\r};^V^[O\t
Xmap! us' unsigned ;^V^[i
Xmap! wh' while () {^V\r}^V^[k0f(a
Xvi .\n"
X
X#
X# Reset to my standard  `vi-environment'
X#
X
XS6 \
X"Qset notimeout
Xunmap! #/
Xunmap! #in
Xunmap! #de
Xunmap! #un
Xunmap! #id
Xunmap! #if
Xunmap! #el
Xunmap! #en
Xunmap! br'
Xunmap! ca'
Xunmap! ch'
Xunmap! co'
Xunmap! de'
Xunmap! do'
Xunmap! dw'
Xunmap! ei'
Xunmap! el'
Xunmap! en'
Xunmap! ex'
Xunmap! fl'
Xunmap! fo'
Xunmap! go'
Xunmap! if'
Xunmap! in'
Xunmap! lo'
Xunmap! ma'
Xunmap! re'
Xunmap! rg'
Xunmap! sc'
Xunmap! sh'
Xunmap! si'
Xunmap! st'
Xunmap! sw'
Xunmap! ty'
Xunmap! un'
Xunmap! us'
Xunmap! wh'
Xvi .\n"
X
X
X# I use my function key F7 for temporary, repetitive things; complicated
X# commands, sequences, etc. Real nice if application allows shell
X# escapes.  Most often used with complicated vi commands. 
X
XS7	'keydef F7\n'
X
X
XF-Help	apropos\\t
XS-Help	man\\t
X
X# Two ways to make a 'shell escape' from vi:
XF-Do	^Z
XS-Do	:!/bin/csh
X
X# To execute remote commands on my preferred systems:
XF14	"/usr/ucb/bin/rsh icodap "
XS14	"/usr/ucb/bin/rsh newgest -l vigna "
X
X
X# Sometime I use bc with the numeric keypad; I find this useful:
XF17	' + '
XF18	' - '
XF19	' * '
XF20	' / '
END_OF_FILE
if test 3610 -ne `wc -c <'sample'`; then
    echo shar: \"'sample'\" unpacked with wrong size!
fi
# end of 'sample'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    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