
			K I S S  Technical notes


Compiling Kiss
--------------

There are basically three versions of Kiss: (a) one that includes readline
support, (b) one that includes getline, and (b) one that contains neither. The
versions are appropriately named "rkiss" (for readline), "gkiss" (for getline)
and "bkiss" (for bare). The biggest executable is of course rkiss, since it
includes editing and filename completion; the smallest is bkiss.

I guess that for a SAR disk (see my Search-And-Rescue disk package on
ftp.icce.rug.nl:/pub/unix/SAR*), you'd use the `getline' version or even the
`bare' version; for reasons of space.

Important note: All three versions are linked by the Makefile to use shared
libraries. They are especially menat for SAR disks, where you have the libs
anyway. If you want to make a Kiss for usage on your HDU (in emergencies, when
the libs disappear or whatever), modify the Makefile to link with the
`-static' flag and re-make.

To compile:

    a. Edit the Makefile and adjust the macros at the top. If you have the
       readline libs, where do they reside? What is your BINDIR if you
       want to install the progs?
    b. Type "make rkiss" (readline), "make gkiss" (getline) or
       "make bkiss" (bare version). The executable file will then be "rkiss"
       or "gkiss" or "bkiss". Or just type "make all" to make all three.
    c. "make rinstall" will "make rkiss" and install it to $(BINDIR) (defined
       in the Makefile); "make binstall" will do the same for the bare
       version. A "make ginstall" will make gkiss and install it.

You will need the following for a successful installation:
    - gcc better than 2.5.8
    - libs 4.6.27 or better
    - libreadline.a and libtermcap.a if you want to make the readline version
    - bison and flex.

You won't need the getline sources, I've included them in the archive of the
sources (though I am not the author neither the maintainer).


When you change the sources
---------------------------

When you change the sources, please adher to the following:

    a. Always inform me if you have useful additions! Mail me at
       karel@icce.rug.nl. I'd like to have the latest version too! Also
       describe what you've changed, and why you've changed it -- instead of
       just mailing me some diffs.

    b. Edit the file "subversion.h" (read that as sub-version, not as
       revolution) and increment the number there. That will hopefully keep
       track of compilations. The versions are displayed with Kiss' "ver"
       command.
    

Adding a built-in command
-------------------------

This section describes how to create a built-in command, say "tar" (not that
you would want to do that.. but whatever). Before you decide that you need it,
please consider:

    a. Built-ins should be what you expect everyone to need in a rescue-disk
       environment. E.g., "ls". But not "loadkeys".

    b. Beware of promoting hardware-dependant stuff to built-ins. E.g.,
       "e2fsck" may be what everyone uses, but I don't think that it should be
       a built-in command.


1. Making the command known to Kiss.

    Edit kiss.h and add a function declaration to the list of external
    functions. E.g., if you implement the "tar" command, then add a line

		extern int dotar (Stringstack s);

    to kiss.h. The function must return an integer (exit status) and must
    expect a Stringstack as its only argument. We'll get to Stringstacks
    later. Hint: enter the function name in alphabetical order, somewhere
    between the other doxxxx() declarations.

    Next, edit kiss.c and add to the table at the top:

		{ "tar",	dotar,	    0 },

    This table is used by the parser: when the string "tar" is seen, then
    dotar() will be called. The last field (0) means that dotar() can be
    called by a forked-off child process. A 1 in the last field means that the
    command is a `level zero' command, e.g., "setenv" is such a command: it
    must be handled by the parent Kiss and not by a child process. Generally,
    the built-in commands can be handled by children.

    Now edit dohelp.c (the "help" command) and add the description of your
    command to the list. It will then be shown when someone requests "help".

    Finally, edit the Makefile and add dotar.o to the list of objects.


2. Implementing your function.

    I strongly suggest that you implement your function dotar() in a file
    dotar.c (hence the name dotar.o added to the Makefile). That helps keeping
    the overview over what's where.

    Here's the start of your function, comments illustrate arguments etcetera:

	#include "kiss.h"	/* all includes are in kiss.h, no need to 
				   request stdio.h etc. too */

	int dotar (Stringstack s)
	/* function is called: dotar
	   returns: an int (exit status), 0 if all is ok
	   expects: a Stringstack, which holds two fields:
		    nstr : number of stored strings (`argc' like counter)
		    str  : array of strings	    (`argv' like list)
        */
	{
	    /* now for some options parsing, e.g. -c -v -z -f
	       will be recognized; also -h for help */

	    register int
		opt;

	    while ( (opt = getopt (s.nstr, s.str, "cvzfh")) != -1 )
		switch (opt)
		{
		    case 'v':
			....
			break;
		    ...
		    case 'h':
		    default:
			error ("Bad commandline.\n"
			       "Usage: %s [-cvzf] archive [file(s)]\n",
			       progname);
                }				    
	....
	}


    Implementation comments:

	- char *progname holds the `bare' program name, in your case "tar".
	  Use it in printf()'s or whatever. Using the actual invocation name
	  is better than hardwiring "tar" or whatever name; e.g., if you
	  change the command name to "mytar" in kiss.c then "mytar" will show
	  up as "progname" in your displayed messages.
	- s.nstr and s.str hold the arguments, like argc/argv
	- Use getopt() and optind to parse the flag arguments. See the
	  manpages. Always enable a `-h' flag, which with the `default' case,
	  shows help.
	- Use the function error() to show error messages and terminate; it
	  works just like printf() but prints "program: " first.
	- Use warning() to show warnings, works like error() but doesn't
	  terminate.

    If you need auxiliary functions to your dotar() function, you can either
    make them statics in dotar.c or declare them in kiss.h and implement them
    in separate source files. In the latter case you'd of course need to add
    the names of those files to the Makefile.
    
If you want to see a small example, check out dotouch.c which implements the
"touch" command. It's about the smallest thing that I can think of.
