
============================================================================

			    K I S S   User Guide

		       Karel Kubat (karel@icce.rug.nl)

============================================================================

Starting Kiss
-------------

Kiss supports a lot of flags. Try "[brg]kiss -h" if you want to see the list.
The executable that you want to start is either "bkiss", "gkiss" or "rkiss", I
suggest "rkiss" if you have all of them (you have now, since you've unpacked
the archive).  The "bkiss" version ("b" for "bare") has no line editing
facilities, but is the smallest - so it's ideal for a rescue disk. The "gkiss"
program has getline support, it has line editing. The "rkiss" finally has line
editing and filename completion. Supported flags by all the Kiss programs are,
e.g., "-c command" to run a command, or "file [file..]" to load scripts.  

Mostly, you'll want Kiss just started in interactive mode, without any flags.
To get a feel for how things work, try "help". If too much info scrolls off
the screen, try "help | more". That will show all the built-in commands and an
overview of relevant environment settings.

A handy thing to keep in mind: most built-in commands recognize the "-h" flag.
If you want to know how the built-in "ls" works, try "ls -h".


The command parser
------------------

Kiss has an input parser which works as follows. I'm just describing some of
the highlights here, so that you know.

    The input consists of one or more lines. You can terminate Kiss by
    stopping the input: either send an EOF character (^D) or type "exit" (or,
    "exit 3" if you want exit status 3). See the info which the "help" command
    provides about "exit". (Note: the getline version requires you to type ^D
    twice to exit, it's some quirk.)

    Each line consists of statements, separated by pipe tokens and terminated
    by a newline token. Which means that the command will be interpreted as
    soon as you hit enter (what did you expect). The pipe tokens work in the
    normal fashion: "a | b | c | d" will start four programs, "a" to "d",
    where each next program receives on its standard input the output of the
    previous program. The output of "d" (if any) goes to the screen, the input
    of "a" (if any) comes from the keyboard. Kiss doesn't understand piping of
    other streams than stdin and stderr. Standard-error messages will always
    appear on screen. Furthermore, the parser understands the "&" character
    when it appears as the last thing on the input line. Note that "&" marks
    may not appear elsewhere.

    Besides the newline-terminator, Kiss knows about the ";" character. E.g.,
    "ls ; ls" will run two "ls" commands for you. The ";" character is handy
    in aliases (described later), but in interactive mode it's just like
    typing a newline. Incidentally, this means that if you want a 'real'
    semicolon (e.g., as an argument to the "find" program), you must `protect'
    it by quoting it; as in:
		    prompt>  find / -exec ls {} ';'
    Quoting special characters is always done with single or double quotes,
    the same reasoning holds for pipe tokens "|" and redirections "<" etc..
    Quoting special characters is NOT done with a backslash, like you may be
    used to.

    A statement (i.e., info between the "|" marks or just the strings when no
    piping is needed) is either the `recall' command or a `real' command. The
    recall command is very handy: those familiar with Tcsh surely know it. It
    recalls a command from the "history list". E.g., "!d" re-runs the last
    command that starts with "d". Another history-related command is
    "history", which shows what your previous commands are. Try "history |
    more" if the list is getting long. If you find typing "history" too much,
    try "alias his history" and then "his | more". Or even:  "alias mhis
    'history | more'" (note the quoting around 'history|more'), and then
    "mhis".

    Commands which don't recall previously entered commands may be followed by
    "< file" and/or "> file" or ">> file", forcing redirection of stdin or
    stdout to a file. Kiss doesn't support redirection of stderr.

    In the end, commands are just strings. Kiss knows four types of strings:

	a. Simple strings are just what they are, e.g. names of program files.
	   Simple strings are subject to expansion of wildcards (e.g., *.c
	   becomes a lot of strings) etc.

	b. Quoted strings are enclosed by " or '. Such strings aren't subject
	   to expansion. This is the way to protect `special' characters like
	   pipe tokens, semicolons or "<" and ">".

	c. Backquoted strings are enclosed by `. These are substituted with
	   the output of a program; e.g. "echo `ls`". 

	d. Variables are in the form $STUFF. Note that Kiss only knows of
	   variables which are named in upper case. Also note that Kiss
	   doesn't understand variable names in the form ${STUFF}.

    Strings which contain "~/" are rewritten so that the tilde is expanded to
    the user's home directory. E.g, when you type "cd ~/bin" then you
    change-dir to "$HOME/bin".


Environment access
------------------

Kiss has four commands which access the environment.

    a. "printenv" shows the environment in a series of lines "VAR=value". You
       can also look for only one environment string, e.g. "printenv PATH".
    b. "setenv VAR value" sets the environment variable "VAR" to "value. E.g.,
		prompt>  setenv PATH $PATH:/usr/local/bin
       adds "/usr/local/bin" to the search path.
    c. The syntax "VAR=value" is a synonym for "setenv". Spaces are allowed;
       "VAR = value" is the same as "VAR=value".
    d. The command "unsetenv VAR" removes the "VAR" from the environment.

Of course, you can type "$VAR" to get the value of a variable, as in
		prompt> echo $PATH

Relevant environment variables are:

    a. $PATH is of course the search-path for programs. A handy command here
       is "where", e.g., try "where ls". It will show that "ls" is a built-in
       command but also resides in "/bin/ls".
    b. $HOME is set by Kiss to the user's home directory.
    c. $PWD is maintained by Kiss and always holds the current working
       directory. The command "pwd" prints it.
    d. $SHELL is the name of the shell interpreter, e.g.
       "/usr/local/bin/kiss".
    e. $SHLVL is the shell level: initially "1". As Kiss forks to start
       programs, $SHLVL is incremented. This variable is mainly for internal
       use.
    f. $UID is the numerical user ID, $USER is the user name (when available).
    g. $PROMPT tells Kiss what to display as the input prompt. You can put
       special characters in the setting:
	    %p gives the current working directory,
	    %u gives the username,
	    %n gives a newline.
       The default $PROMPT is "[%u] %p > ", which gives something like
       "[username] /tmp > " as the prompt.
    h. $$ is the shell's process ID.
    i. $? is the last command's exit status.
    j. $! is the last command's process ID.
    

Aliases
-------

Kiss understands a special command called "alias", to set up an alias for
a command. Example:

    prompt> alias d  ls -Fla
    prompt> d				    # this runs "ls -Fla"
    prompt> d /tmp			    # this runs "ls -Fla /tmp"

If you postfix any arguments to an alias (as in "d /tmp"), then those
arguments will be postfixed to the expanded command (giving "ls -Fla /tmp").

You can mention arguments in aliases, use $1, $2 etcetera. E.g.:

    prompt> alias dx  'ls -l *.$1'
    prompt> dx c			    # this runs "ls -l *.c"

Here you need to mention "$1" explicitely because you want that argument to be
appended to "ls -l *." without spaces in between.

This way you control where arguments exactly appear in an alias. Another handy
alias for X users:

    prompt> alias xvi 'xterm -e vi $1 &'
    prompt> xvi somefile		    # runs xterm -e vi somefile &

Here you need to mention "$1" explicitely because following the argument you
want the "&" character.

The "alias" command can also list aliases (when invoked without arguments) or
a particular alias (when invoked with one argument). Once you invoke "alias"
with two or more arguments, you're defining a new alias or redefining an old
one.

I call aliases which invoke more than one command `chained aliases'. E.g.:

    prompt> alias go 'a ; b'
    prompt> go			    # this runs first "a", then "b"

Kiss only understands simple alias chaining, so beware. Some restrictions are:

    a. The commands in a chained alias must be separated by a ; in spaces. So:
	prompt> alias go 'a;b'	    # won't work, you need 'a ; b'
       You really need the space before AND after the semicolon. This
       requirement is btw. only true in aliases, the semicolon doesn't need
       spaces around it when you enter it interactively. (It's not a perfect
       world..)

    b. Chained aliases may only consist of two commands, not more. E.g.:
	prompt> alias go 'a ; b ; c'	    # won't work, three commands
      To run three commands via an alias, you need an intermediate alias:
	prompt> alias go	'a ; go_1'
	prompt> alias go_1	'b ; c'
	prompt> go			    # now this runs a, b and then c

    c. The second command in an alias isn't passed arguments, you just can run
       it `bare'.


Startup files
-------------

Kiss tries to load two startup files, one system-wide resource and one
user-owned resource. The files are:

    a. /etc/kiss.rc : system-wide file
    b. ~/.kissrc    : user-owned file

You can put anything in the startup files, including "cd" commands, "echo", or
whatever. The files are however typically used for auto-loading aliases.

Here's a favorite of mine, which you can put into your ~/.kissrc:

    # my favorite editor
    EDITOR = jove

    # how to re-read ~/.kissrc
    alias reload	source ~/.kissrc

    # how to edit ~/.kissrc and re-read it immediately
    alias ek		'$EDITOR ~/.kissrc ; reload'


The built-in commands
---------------------

Here follows a brief description of the built-in commands. Most of them will
work as expected; I'm just focusing on the differences.

A handy command to find out whether a command is a built-in is "where"; e.g.,
"where mount" will show where an external "mount" program resides and that
"mount" is an internal command. If you prefer to start the external command
instead of the internal one, just type the full name (say "/sbin/mount")
instead of just "mount".

    "cat": Doesn't support buffer sizes or what else you need. Just prints
	stdin or a file to stdout.

    "chmod": You can use here mode strings like "a+x" (for all: add execute
	bit), or octal numbers (644 for owner: r/w, group: r, others: r). The
	mode strings however don't know about sticky or setuid bits, just
	r/w/x. Use octal modes to set or clear s-bits.

    "chown": Just changes the owner, you can't change both owner and group
	with one command. Use "chgrp" to change group ownership.

    "cp": Is pretty clever, copies files while preserving `holes'. This means
	unfortunately that "cp" is slow. Needs rewriting.  Furthermore, "cp"
	only copies _files_, not pipes or devices. Use "mknod" to create
	devices. "cp" does know about symlinks though, it will copy links if
	you give it the "-d" flag.

	Also, "cp" may not synthesize destination pathnames as you're used to.
	I never figured out the original "cp" anyway.

    "grep": Just a subset of the real "grep", though it understands true
	regular expressions. Only supports "-i" (ignore case) and "-v" (show
	non-matching lines) flags.

    "kill": Doesn't support symbolic names for signals (e.g. "-HUP"). Just the
	numbers.

    "ln": Always requires that the link to create doesn't exist, you cannot
	overwrite files with new links. Not even with the "-f" flag. The "ln"
	command interprets its "-f" flag a bit off: for me it means "create a
	link even if it points nowhere". Hm.

    "ls": Output in columns is sorted left-to-right, while the original "ls"
	sorts top-to-bottom. I don't intend on fixing that. Also, dates and
	times are displayed a bit non-standard with "ls -l".

    "mknod": Always creates pipes or devices with octal mode 644. There's no
	"--mode" flag. Use "chmod" to adjust the mode.

    "more": No page-back commands, and you must hit ENTER after each input.
	Always pauses after 23 lines of output. Doesn't recognize too long
	lines.

    "mount": As of version 0.13, mount does update /etc/mtab, so you can get a
	listing of what's mounted and what not (thanks to Constantine
	Rasmussen, cdr@sme.siemens.com). However, mount doesn't inspect
	/etc/fstab so that you never can "mount all". Also, mount doesn't
	support read/only mounting, all mounts are done read/write.

    "setenv" and its alias "VAR=value": Only knows about variables in upper
	case. You can't make variables in lower case.

    "source": Doesn't check `circular' sourcing, you could e.g. source file
	"a" which contains "source b", so that "b" is sourced, but if "b"
	sources "a" again then you have an endless loop.

    "touch": Only sets file times to the current time.

    "wc": The word counting is a bit off, I couldn't figure out what the
	orginal "wc" considers one `word'. The line and character counts are
	ok though.


Signal handling
---------------

Kiss will try to stay alive as long as possible. I know that the program isn't
perfect: if it is signalled with a segmentation fault, it tries to reload. I
know that this is non-standard, but I want to provide some interpreter access
when things go haywire: I expect Kiss to be used on e.g., rescue disks, where
you don't want your shell interpreter to die. Other signals which are caught
by Kiss are:

    a. 10 and 12; SIGUSR1 and SIGUSR2. Kiss will try to reload when you send
       it this signal. E.g., try
			    prompt> kill -10 $$
    b. Signal 2 (SIGINT, sent when you type ^C) is by default ignored. Start
       Kiss with the "-C" flag if you want Kiss to abort with ^C.
    c. Other signals have the default action; e.g., signal 15 will kill Kiss.
       (Signal 9 will too ;-).
       
